You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL Server查询:按FieldID获取各ChangeField的首次与末次变更值

解决方案:按FieldID+ChangeField分组提取首次/末次变更值及最新日期

当然可以实现这个需求!针对你给出的变更记录表,我们可以用SQL的窗口函数或者子查询聚合的方式来快速得到目标结果,下面提供两种适配不同数据库环境的方案:

原始数据

先把你的原始表数据整理成更清晰的格式(假设表名为change_log):

FieldID | ChangeField | OldValue | NewValue | ChangeDate
--------|-------------|----------|----------|----------------------
1       | interest    | 1.5      | 1.2      | 2018-05-01 13:00:00
1       | interest    | 1.2      | 1.3      | 2018-05-01 14:00:00
1       | quantity    | 2        | 1        | 2018-05-01 15:00:00
1       | quantity    | 1        | 2        | 2018-05-01 16:00:00
1       | quantity    | 2        | 3        | 2018-05-01 17:00:00
2       | quantity    | 10       | 20       | 2018-05-01 18:00:00
2       | quantity    | 20       | 30       | 2018-05-01 19:00:00

方案1:使用窗口函数(推荐,支持MySQL8.0+/PostgreSQL/SQL Server等)

窗口函数可以高效地给分组内的记录排序标记,然后提取我们需要的首尾值:

WITH ranked_records AS (
    SELECT 
        FieldID,
        ChangeField,
        OldValue,
        NewValue,
        ChangeDate,
        -- 给每个分组内的记录按时间升序编号,1就是首次变更
        ROW_NUMBER() OVER (PARTITION BY FieldID, ChangeField ORDER BY ChangeDate ASC) AS first_change,
        -- 给每个分组内的记录按时间降序编号,1就是末次变更
        ROW_NUMBER() OVER (PARTITION BY FieldID, ChangeField ORDER BY ChangeDate DESC) AS last_change
    FROM change_log
)
SELECT 
    FieldID,
    ChangeField,
    -- 提取首次变更的OldValue
    MAX(CASE WHEN first_change = 1 THEN OldValue END) AS OldValue,
    -- 提取末次变更的NewValue
    MAX(CASE WHEN last_change = 1 THEN NewValue END) AS NewValue,
    -- 取分组内最新的变更日期
    MAX(ChangeDate) AS dtChangeDate
FROM ranked_records
GROUP BY FieldID, ChangeField
ORDER BY FieldID, ChangeField;

方案2:子查询聚合(适配老版本数据库,比如MySQL5.x)

如果你的数据库不支持窗口函数,可以用子查询来分别获取首次和末次值:

SELECT 
    main.FieldID,
    main.ChangeField,
    -- 子查询取该分组最早的OldValue
    (SELECT OldValue FROM change_log 
     WHERE FieldID = main.FieldID AND ChangeField = main.ChangeField 
     ORDER BY ChangeDate ASC LIMIT 1) AS OldValue,
    -- 子查询取该分组最晚的NewValue
    (SELECT NewValue FROM change_log 
     WHERE FieldID = main.FieldID AND ChangeField = main.ChangeField 
     ORDER BY ChangeDate DESC LIMIT 1) AS NewValue,
    -- 取分组内最新的变更日期
    MAX(main.ChangeDate) AS dtChangeDate
FROM change_log main
GROUP BY main.FieldID, main.ChangeField
ORDER BY main.FieldID, main.ChangeField;

执行结果

两种方案都会输出你预期的结果:

FieldID | ChangeField | OldValue | NewValue | dtChangeDate         | 说明
--------|-------------|----------|----------|----------------------|---------------------------------------------
1       | interest    | 1.5      | 1.3      | 2018-05-01 14:00:00  | interest初始值1.5,最终值1.3,最新变更时间14点
1       | quantity    | 2        | 3        | 2018-05-01 17:00:00  | quantity初始值2,最终值3,最新变更时间17点
2       | quantity    | 10       | 30       | 2018-05-01 19:00:00  | quantity初始值10,最终值30,最新变更时间19点

注意事项

  • 记得把change_log替换成你的实际表名
  • 如果同分组内存在同一时间多条变更记录,可以在排序时增加额外字段(比如主键)保证排序的唯一性
  • 不同数据库的语法细节略有差异:比如SQL Server用TOP 1代替LIMIT 1,Oracle用ROWNUM或者窗口函数实现

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:01:05