You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

对比两张数据表并返回新旧变更明细的实现方法

嘿,这个需求我太熟了!咱们可以通过关联新旧表+条件过滤+字段级对比标注来实现,我给你拆解成具体步骤和SQL示例:

核心思路
  1. 用人员唯一标识(比如员工ID)关联当前表和历史表,确保匹配的是同一个人的新旧记录
  2. 对每个需要对比的字段,用条件语句判断是否变更,清晰标注出新旧值
  3. 最后过滤掉所有字段都没有变更的记录,只保留真正有修改的行
具体SQL示例

假设你的表结构是这样的:

  • 当前表current_employeesemp_id(唯一ID)、namedepartmentsalaryhire_date
  • 历史表historical_employeesemp_idoriginal_nameoriginal_departmentoriginal_salaryoriginal_hire_datechange_timestamp(记录变更发生的时间)

对应的SQL可以这么写:

SELECT
    -- 基础信息:人员ID和变更时间
    c.emp_id,
    h.change_timestamp,
    -- 姓名字段的变更标注,无变更则返回NULL
    CASE
        WHEN c.name <> h.original_name THEN CONCAT('旧值: ', h.original_name, ' → 新值: ', c.name)
        ELSE NULL
    END AS name_change,
    -- 部门字段的变更标注
    CASE
        WHEN c.department <> h.original_department THEN CONCAT('旧值: ', h.original_department, ' → 新值: ', c.department)
        ELSE NULL
    END AS department_change,
    -- 薪资字段的变更标注(数值类型需转字符串拼接)
    CASE
        WHEN c.salary <> h.original_salary THEN CONCAT('旧值: ', CAST(h.original_salary AS CHAR), ' → 新值: ', CAST(c.salary AS CHAR))
        ELSE NULL
    END AS salary_change,
    -- 入职日期字段的变更标注(日期类型转字符串)
    CASE
        WHEN c.hire_date <> h.original_hire_date THEN CONCAT('旧值: ', CAST(h.original_hire_date AS CHAR), ' → 新值: ', CAST(c.hire_date AS CHAR))
        ELSE NULL
    END AS hire_date_change
FROM
    current_employees c
JOIN
    historical_employees h ON c.emp_id = h.emp_id
WHERE
    -- 过滤掉所有字段都无变更的记录
    c.name <> h.original_name
    OR c.department <> h.original_department
    OR c.salary <> h.original_salary
    OR c.hire_date <> h.original_hire_date
关键细节补充
  • NULL值处理:如果字段可能为NULL,直接用<>对比会失效,得改成COALESCE(c.name, '') <> COALESCE(h.original_name, ''),把NULL转成空字符串再对比
  • 多历史记录场景:如果一个人有多次变更历史,建议用MAX(h.change_timestamp)关联最新的一条历史记录,避免返回重复对比结果
  • 自定义标注格式:如果想更灵活,也可以把新旧值分开列,再加一个变更标记,比如:
    SELECT
        c.emp_id,
        h.original_name AS old_name,
        c.name AS new_name,
        CASE WHEN c.name <> h.original_name THEN '✓' ELSE '' END AS name_changed,
        -- 其他字段同理
    FROM ...
    WHERE ...
    

这样处理后,只有真正发生变更的记录会被返回,每个变更字段的新旧值也会清晰展示,完全符合你的需求~

内容的提问来源于stack exchange,提问作者nikih

火山引擎 最新活动