按插入顺序分组行:同SHIFTREF非连续组的SQL分组实现
按连续相同SHIFTREF分组汇总的SQL实现
需求说明
现有包含RECORDREF、SHIFTREF、DATECREATED字段的表格数据,需要按SHIFTREF分组,但被其他SHIFTREF值行隔开的同值组需视为不同分组,且不能将DATECREATED用于GROUP BY子句,最终得到指定的汇总结果。
原始数据
| RECORDREF | SHIFTREF | DATECREATED |
|---|---|---|
| 1 | 3 | 2023/09/19 |
| 2 | 3 | 2023/09/19 |
| 3 | 3 | 2023/09/19 |
| 4 | 3 | 2023/09/20 |
| 5 | 4 | 2023/09/20 |
| 6 | 4 | 2023/09/20 |
| 7 | 4 | 2023/09/20 |
| 8 | 4 | 2023/09/20 |
| 9 | 5 | 2023/09/20 |
| 10 | 5 | 2023/09/20 |
| 11 | 5 | 2023/09/20 |
| 12 | 3 | 2023/09/20 |
| 13 | 3 | 2023/09/20 |
| 14 | 3 | 2023/09/21 |
| 15 | 3 | 2023/09/21 |
期望结果
| SHIFTREF | COUNT | DATE |
|---|---|---|
| 3 | 4 | 2023/09/19 |
| 4 | 4 | 2023/09/20 |
| 5 | 3 | 2023/09/20 |
| 3 | 4 | 2023/09/20 |
解决方案
核心思路是通过窗口函数生成连续分组标识,利用RECORDREF的递增特性判断行的先后顺序,将连续相同的SHIFTREF归为同一组,被隔开的同值则生成新组,最后基于分组标识汇总。
完整SQL语句
SELECT SHIFTREF, COUNT(RECORDREF) AS COUNT, MIN(DATECREATED) AS DATE FROM ( SELECT RECORDREF, SHIFTREF, DATECREATED, -- 生成连续分组ID:当前行与上一行SHIFTREF不同时,累加1 SUM(CASE WHEN SHIFTREF = LAG(SHIFTREF) OVER (ORDER BY RECORDREF) THEN 0 ELSE 1 END) OVER (ORDER BY RECORDREF) AS group_id FROM your_table ) AS grouped_data -- 按SHIFTREF和分组ID分组,确保同SHIFTREF但不连续的组被区分 GROUP BY SHIFTREF, group_id ORDER BY group_id;
语句解释
子查询生成分组ID:
- 使用
LAG(SHIFTREF) OVER (ORDER BY RECORDREF)获取当前行的上一行SHIFTREF值; - 通过
CASE语句判断当前行与上一行SHIFTREF是否相同,不同则标记为1,相同则为0; - 用
SUM()窗口函数累加标记值,生成唯一的group_id,连续相同的SHIFTREF会得到同一个group_id。
- 使用
外层汇总查询:
- 按
SHIFTREF和group_id分组,确保被隔开的同SHIFTREF组被视为不同分组; COUNT(RECORDREF)统计每组的记录数;MIN(DATECREATED)取该组的最早日期(符合期望结果的日期展示需求);- 最后按
group_id排序,保证结果顺序与原始数据的分组顺序一致。
- 按
注意事项
- 必须确保
RECORDREF是按数据插入顺序递增的,否则ORDER BY RECORDREF无法正确反映行的先后顺序,会导致分组错误。
内容的提问来源于stack exchange,提问作者Fatih Büyükegen
相关产品推荐
相关产品推荐

