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

如何用LAG、FIRST_VALUE等函数基于有序查询结果构建分组?

嘿,我来帮你搞定这个分组需求!先把你的原始查询结果整理成清晰的表格:

val1val2val3id
1303130322.03.18 14:00:03.9150000001
1303130322.03.18 14:00:07.8000000002
1303130323.03.18 12:15:03.7980000003
1303130323.03.18 12:15:09.3450000004
9999130323.03.18 21:00:00.0000000005
1303130323.03.18 23:15:09.3450000006
9999130323.03.18 23:18:09.3450000007
9999130323.03.18 23:19:09.3450000008
1303130323.03.18 23:20:09.3450000009
1303130323.03.18 23:55:09.34500000010

从数据来看,我们需要把连续相同val1的行划分为同一个分组,这类场景用LAG结合累加的方式最直接,如果你还需要获取分组的起始信息,FIRST_VALUE也能派上用场,下面给你两种实现方案:

方案1:用LAG标记变化点,生成分组ID

核心思路是:先判断当前行的val1和上一行是否不同,标记变化点;然后对变化点做累加,得到唯一的分组ID。

SELECT 
    val1, val2, val3, id,
    -- 累加变化标记,生成连续分组的ID
    SUM(change_flag) OVER (ORDER BY id) AS group_id
FROM (
    SELECT 
        val1, val2, val3, id,
        -- 第一行没有上一行,直接标记为变化;后续行和上一行val1不同则标记为1
        CASE 
            WHEN LAG(val1) OVER (ORDER BY id) != val1 
                OR LAG(val1) OVER (ORDER BY id) IS NULL 
            THEN 1 
            ELSE 0 
        END AS change_flag
    FROM your_table_name -- 替换成你的实际表名
) t
ORDER BY id;

执行后会得到这样的结果,每个连续相同val1的块都有了统一的group_id:

val1val2val3idgroup_id
1303130322.03.18 14:00:03.91500000011
1303130322.03.18 14:00:07.80000000021
1303130323.03.18 12:15:03.79800000031
1303130323.03.18 12:15:09.34500000041
9999130323.03.18 21:00:00.00000000052
1303130323.03.18 23:15:09.34500000063
9999130323.03.18 23:18:09.34500000074
9999130323.03.18 23:19:09.34500000084
1303130323.03.18 23:20:09.34500000095
1303130323.03.18 23:55:09.345000000105

方案2:结合FIRST_VALUE获取分组起始信息

如果需要每个分组的第一个ID或者第一个时间戳,可以在生成分组ID后,用FIRST_VALUE来提取这些信息:

WITH grouped_data AS (
    SELECT 
        val1, val2, val3, id,
        SUM(change_flag) OVER (ORDER BY id) AS group_id
    FROM (
        SELECT 
            val1, val2, val3, id,
            CASE 
                WHEN LAG(val1) OVER (ORDER BY id) != val1 
                    OR LAG(val1) OVER (ORDER BY id) IS NULL 
                THEN 1 
                ELSE 0 
            END AS change_flag
        FROM your_table_name
    ) t
)
SELECT 
    *,
    -- 获取当前分组的第一个ID
    FIRST_VALUE(id) OVER (PARTITION BY group_id ORDER BY id) AS group_first_id,
    -- 获取当前分组的第一个时间戳
    FIRST_VALUE(val3) OVER (PARTITION BY group_id ORDER BY id) AS group_first_time
FROM grouped_data
ORDER BY id;

关键逻辑说明

  • LAG(val1) OVER (ORDER BY id):按id排序,拿到当前行的上一行val1,用来判断是否触发分组变化。
  • SUM(change_flag) OVER (ORDER BY id):对变化标记做累加,每次遇到变化点(change_flag=1),分组ID就会递增,自然把连续相同val1的行归为一组。
  • FIRST_VALUE:在每个分组内,按id排序后取第一个值,方便后续对分组做统计、溯源等操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:15:09