基于连续Section分组聚合MIN(Low)与MAX(High)的SQL实现需求
处理连续相同Section的分组聚合需求
原始数据(按Low、High排序)
| Group | Section | Low | High |
|---|---|---|---|
| A | 01 | 01 | 10 |
| A | 01 | 11 | 15 |
| A | 01 | 18 | 18 |
| A | 01 | 19 | 25 |
| A | 02 | 26 | 30 |
| A | 02 | 31 | 32 |
| A | 01 | 33 | 40 |
| A | 01 | 41 | 41 |
期望输出结果
需要对连续出现的同一Section进行聚合,每当Section发生变更前,取该连续组的最小Low和最大High,结果如下:
| Group | Section | Low | High |
|---|---|---|---|
| A | 01 | 01 | 25 |
| A | 02 | 26 | 32 |
| A | 01 | 33 | 41 |
问题说明
单纯按Group和Section全局分组的SQL无法实现这个需求,比如以下语句会把所有Section为01的行合并成一组,不符合连续分组的要求:
select [group], [section], min([low]), max([high]) from table group by [group], [section]
解决方案
可以通过窗口函数识别连续的Section分组,步骤如下:
- 使用
LAG()函数获取上一行的Section值,判断当前行与上一行的Section是否相同 - 根据判断结果生成分组标识(当Section变化时,分组ID递增)
- 按Group和生成的分组ID进行聚合,得到每个连续Section组的最小Low和最大High
以SQL Server为例,实现代码如下:
WITH ranked_data AS ( SELECT [Group], [Section], [Low], [High], -- 生成连续分组ID:当当前Section与上一行不同时,分组ID+1 SUM(CASE WHEN LAG([Section]) OVER (PARTITION BY [Group] ORDER BY [Low]) = [Section] THEN 0 ELSE 1 END) OVER (PARTITION BY [Group] ORDER BY [Low]) AS group_id FROM your_table ) SELECT [Group], [Section], MIN([Low]) AS Low, MAX([High]) AS High FROM ranked_data GROUP BY [Group], [Section], group_id ORDER BY MIN([Low]);
如果是MySQL 8.0+或PostgreSQL,语法类似,只需调整关键字的引号(比如MySQL用反引号,PostgreSQL用双引号或不加)。
内容的提问来源于stack exchange,提问作者user675065
相关产品推荐
相关产品推荐

