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

SQL Server T-SQL:基于值的CTE ROW_NUMBER() OVER PARTITION需求调整

问题分析

需要基于NAME、VAL1、VAL2生成序号,要求:

  • 结果按DT日期降序排列
  • 按VAL2的连续分组分配相同序号(比如PN1前2行、PN3单独行、PN1后3行各自为一组,同组序号一致)

当前使用PARTITION BY NAME,VAL1,VAL2的ROW_NUMBER()函数会把所有相同VAL2的行归为同一分区,无法区分非连续的相同VAL2区块,因此不符合预期。


示例数据

NAMEVAL1VAL2DT
AXPN12024-05-03
AXPN12024-05-02
AXPN32024-05-01
AXPN12024-04-30
AXPN12024-04-29
AXPN12024-04-28

当前SQL语句

SELECT 
    NAME, VAL1, VAL2, DT,
    ROW_NUMBER() OVER (PARTITION BY NAME, VAL1, VAL2 ORDER BY DT DESC) AS seq
FROM your_table
ORDER BY DT DESC;

当前不符合预期的结果

NAMEVAL1VAL2DTseq
AXPN12024-05-031
AXPN12024-05-022
AXPN32024-05-011
AXPN12024-04-303
AXPN12024-04-294
AXPN12024-04-285

期望结果

NAMEVAL1VAL2DTseq
AXPN12024-05-031
AXPN12024-05-021
AXPN32024-05-012
AXPN12024-04-303
AXPN12024-04-293
AXPN12024-04-283

解决方案

核心思路是识别连续相同VAL2的区块,而非单纯按VAL2分区。可以通过LAG()函数标记VAL2的变化点,再通过累计求和生成分组序号。

实现SQL

WITH val2_change AS (
    SELECT 
        NAME, VAL1, VAL2, DT,
        -- 标记当前行与上一行(DT降序)的VAL2是否不同
        CASE WHEN LAG(VAL2) OVER (PARTITION BY NAME, VAL1 ORDER BY DT DESC) != VAL2 THEN 1 ELSE 0 END AS change_flag
    FROM your_table
),
grouped_seq AS (
    SELECT 
        *,
        -- 累计变化标记生成连续分组的序号
        SUM(change_flag) OVER (PARTITION BY NAME, VAL1 ORDER BY DT DESC) + 1 AS seq
    FROM val2_change
)
SELECT NAME, VAL1, VAL2, DT, seq
FROM grouped_seq
ORDER BY DT DESC;

逻辑解释

  1. 标记VAL2变化点:用LAG(VAL2)获取DT降序后上一行的VAL2值,和当前行对比,若不同则记为1(表示进入新分组),相同记为0。
  2. 生成分组序号:对change_flag进行累计求和,每遇到一个1,序号自动加1,这样连续相同的VAL2行会被分到同一组,得到相同的序号。
  3. 最终按DT降序输出,完全匹配期望结果。

如果你的数据库支持简化窗口范围写法,SUM(change_flag)的窗口子句可以省略ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW,因为默认就是从起始行到当前行的累计。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 21:13:09