下表 - 按[低]、[高]排序
团体 | 部分 | 低 | 高 |
---|---|---|---|
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]
更改之前,我都希望获得MIN(Low)
和MAX(High)
。
团体 | 部分 | 低 | 高 |
---|---|---|---|
A | 01 | 01 | 25 |
A | 02 | 26 | 32 |
A | 01 | 33 | 41 |
显然,这太简单了,行不通
select [group], [section], min([low]), max([high])
from table
group by [group], [section]
这称为间隙和孤岛,您希望将事物分组,直到发生变化。
我通常采用这个三阶段解决方案:
;WITH data AS (
SELECT *
FROM
(
VALUES (N'A', N'01', N'01', 10)
, (N'A', N'01', N'11', 15)
, (N'A', N'01', N'18', 18)
, (N'A', N'01', N'19', 25)
, (N'A', N'02', N'26', 30)
, (N'A', N'02', N'31', 32)
, (N'A', N'01', N'33', 40)
, (N'A', N'01', N'41', 41)
) t ([Group],Section,Low,High)
)
SELECT grouping, [group], MIN(Low), MAX(high) /* 3 */
FROM (
SELECT COUNT(flag) OVER(partition BY [group] ORDER BY low rows BETWEEN unbounded preceding AND CURRENT row) AS grouping /* 2 */
, *
FROM (
SELECT CASE WHEN lag(section) OVER(partition BY [group] ORDER BY low) <> section THEN 1 END AS flag /* 1 */
, *
FROM data
) x
) x
GROUP BY [group], grouping
flag
,它表示如果先前的值与当前值不同,则每次此标志变为 1 时,都是新组的开始。rows between unbounded preceding and current row
主要是 sql server goo,它提高了窗口聚合的性能输出:
分组 | 组 | 最小低 | 最大高度 |
---|---|---|---|
0 | A | 01 | 25 |
1 | A | 26 | 32 |
2 | A | 33 | 41 |
PS:注意低/高值,因为你使用
01
它们可能不是真正的整数而是 varchar,那么你必须确保它们都填充到相同的长度,因为 varchar 99
更比100