如何为连续相同价格的行生成独立GroupID
问题描述
我有如下数据表:
| ProductID | Price | ID |
|---|---|---|
| 90271 | 569 | 1 |
| 90271 | 455 | 2 |
| 90271 | 669 | 3 |
| 90271 | 535 | 4 |
| 90271 | 535 | 5 |
| 90271 | 535 | 6 |
| 90271 | 419 | 7 |
| 90271 | 300 | 8 |
| 90271 | 419 | 9 |
| 90271 | 419 | 10 |
| 90271 | 535 | 11 |
需要添加一个GroupID列,将连续相同价格的行归为同一个GroupID,价格变化时生成新的GroupID。直接用DENSE_RANK()不行,因为它会把ID4、5、6、11的行分配相同的GroupID,不符合需求。期望结果如下:
| ProductID | Price | ID | GroupID |
|---|---|---|---|
| 90271 | 569 | 1 | 1 |
| 90271 | 455 | 2 | 2 |
| 90271 | 669 | 3 | 3 |
| 90271 | 535 | 4 | 4 |
| 90271 | 535 | 5 | 4 |
| 90271 | 535 | 6 | 4 |
| 90271 | 419 | 7 | 5 |
| 90271 | 300 | 8 | 6 |
| 90271 | 419 | 9 | 7 |
| 90271 | 419 | 10 | 7 |
| 90271 | 535 | 11 | 8 |
解决方案
可以通过**窗口函数LAG()**结合累加标识的方式实现,核心思路是:
- 用
LAG(Price)获取当前行的上一行Price值 - 比较当前行Price和上一行是否相同,生成变化标识(不同则为1,相同则为0)
- 对变化标识做累加求和,得到连续相同Price的分组ID
SQL 代码示例
SELECT ProductID, Price, ID, SUM(change_flag) OVER (ORDER BY ID) AS GroupID FROM ( SELECT ProductID, Price, ID, -- 第一行无前置行,默认标记为1;后续行价格变化时标记为1,否则0 CASE WHEN LAG(Price) OVER (ORDER BY ID) != Price OR LAG(Price) OVER (ORDER BY ID) IS NULL THEN 1 ELSE 0 END AS change_flag FROM your_table_name ) t;
代码解释
- 内层子查询:通过
LAG(Price) OVER (ORDER BY ID)获取当前行的上一行价格,判断是否与当前行价格不同,生成change_flag。第一行因无前置行,LAG返回NULL,直接标记为1。 - 外层查询:对
change_flag按ID顺序累加求和,每次遇到价格变化时累加值+1,从而生成连续相同价格的分组ID。
如果数据需要按ProductID分组(比如存在多个ProductID时),只需在窗口函数中添加PARTITION BY ProductID:
SELECT ProductID, Price, ID, SUM(change_flag) OVER (PARTITION BY ProductID ORDER BY ID) AS GroupID FROM ( SELECT ProductID, Price, ID, CASE WHEN LAG(Price) OVER (PARTITION BY ProductID ORDER BY ID) != Price OR LAG(Price) OVER (PARTITION BY ProductID ORDER BY ID) IS NULL THEN 1 ELSE 0 END AS change_flag FROM your_table_name ) t;
内容的提问来源于stack exchange,提问作者jenda3
相关产品推荐
相关产品推荐

