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

如何使用或不使用LAG函数查询列的最后变更值及变更日期

找出列中最后变更的值及对应日期的两种实现方法

假设我们有一张记录数值随时间变化的表(比如包含id、record_date、current_value字段),需要提取每个分组(如id)最后一次数值发生变更的具体值和对应的日期。下面提供两种实现方案:

方法一:用LAG函数快速实现

LAG函数能直接获取同一分组中上一行的数值,结合窗口函数可以轻松标记出变更行,再筛选最后一条即可。

示例SQL

WITH change_marks AS (
    SELECT 
        id,
        record_date,
        current_value,
        -- 标记值发生变更的行:首次记录或与上一行值不同
        CASE 
            WHEN LAG(current_value) OVER (PARTITION BY id ORDER BY record_date) IS NULL 
                OR LAG(current_value) OVER (PARTITION BY id ORDER BY record_date) != current_value
            THEN 1
            ELSE 0
        END AS is_change
    FROM value_changes
),
latest_changes AS (
    SELECT 
        id,
        current_value AS last_changed_value,
        record_date AS last_change_date,
        -- 给每个分组的变更行按日期倒序排名
        ROW_NUMBER() OVER (PARTITION BY id ORDER BY record_date DESC) AS rn
    FROM change_marks
    WHERE is_change = 1
)
SELECT id, last_changed_value, last_change_date
FROM latest_changes
WHERE rn = 1;

逻辑说明

  1. change_marks CTE里,用LAG对比当前行和上一行的数值,标记出所有值变化的行(包括每个分组的第一条记录,因为它是初始值)
  2. latest_changes CTE里,给每个分组的变更行按日期倒序排号,取排名为1的就是最后一次变更的记录

方法二:不使用LAG函数的实现方案

如果数据库不支持LAG函数,或者你不想用窗口函数,可以通过分组关联的方式实现。

方案1:结合分组与窗口函数(无LAG)

WITH value_first_dates AS (
    SELECT 
        id,
        current_value,
        MIN(record_date) AS first_change_date
    FROM value_changes
    GROUP BY id, current_value
),
latest_change AS (
    SELECT 
        id,
        current_value AS last_changed_value,
        first_change_date AS last_change_date,
        ROW_NUMBER() OVER (PARTITION BY id ORDER BY first_change_date DESC) AS rn
    FROM value_first_dates
)
SELECT id, last_changed_value, last_change_date
FROM latest_change
WHERE rn = 1;

方案2:纯关联查询(无窗口函数)

适合不支持窗口函数的老版本数据库:

SELECT 
    v.id,
    v.current_value AS last_changed_value,
    v.record_date AS last_change_date
FROM value_changes v
INNER JOIN (
    SELECT 
        id,
        MAX(first_change_date) AS latest_date
    FROM (
        SELECT 
            id,
            current_value,
            MIN(record_date) AS first_change_date
        FROM value_changes
        GROUP BY id, current_value
    ) t
    GROUP BY id
) t ON v.id = t.id AND v.record_date = t.latest_date
WHERE NOT EXISTS (
    SELECT 1
    FROM value_changes v2
    WHERE v2.id = v.id 
      AND v2.record_date > v.record_date 
      AND v2.current_value != v.current_value
);

逻辑说明

  • 方案1先分组得到每个分组下每个数值的首次出现日期,然后取每个分组中最大的首次日期对应的数值,就是最后一次变更的值
  • 方案2通过子查询找到每个分组的最晚变更日期,再关联原表,同时确保该日期之后没有其他数值变更,最终得到最后一次变更记录

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 06:37:31