這應該爲你工作:
DECLARE @T TABLE (Start INT, [End] INT, Value VARCHAR(100));
INSERT @T (Start, [End], Value)
VALUES
(0, 1, 'Banana'), (1, 3, 'Banana'), (3, 4, 'Orange'), (4, 7, 'Orange'),
(7, 8, 'Apple'), (8, 9, 'Apple'), (9, 10, 'Apple'), (10, 15, 'Apple'),
(20, 22, 'Apple'), (22, 23, 'Apple'), (23, 28, 'Banana'), (28, 30, 'Banana');
WITH CTE AS
( SELECT t.[Start],
t.[End],
t.[value],
IsStart = ISNULL(c.IsStart, 1)
FROM @T AS T
OUTER APPLY
( SELECT TOP 1 IsStart = 0
FROM @T AS T2
WHERE T2.Value = T.Value
AND T2.[End] = T.Start
) AS c
)
SELECT Value, Start = MIN(Start), [End] = MAX([End])
FROM CTE AS T
OUTER APPLY
( SELECT SUM(IsStart)
FROM CTE AS T2
WHERE T2.Value = T.Value
AND T2.Start <= T.Start
) g (GroupingSet)
GROUP BY Value, GroupingSet
ORDER BY Start;
的第一步是確定每一個是新範圍的開始記錄。這一部分:
SELECT t.[Start],
t.[End],
t.[value],
IsStart = ISNULL(c.IsStart, 1)
FROM @T AS T
OUTER APPLY
( SELECT TOP 1 IsStart = 0
FROM @T AS T2
WHERE T2.Value = T.Value
AND T2.[End] = T.Start
) AS c
會給:
Start End value IsStart
0 1 Banana 1
1 3 Banana 0
3 4 Orange 1
4 7 Orange 0
7 8 Apple 1
8 9 Apple 0
9 10 Apple 0
10 15 Apple 0
20 22 Apple 1
然後你就可以通過識別當前記錄之前啓動的範圍數量創造獨特的羣體,基本上將運行總計被分割的IsStart
列值。這是正在這裏進行:
SELECT *
FROM CTE AS T
OUTER APPLY
( SELECT SUM(IsStart)
FROM CTE AS T2
WHERE T2.Value = T.Value
AND T2.Start <= T.Start
) g (GroupingSet);
,並提供:
Start End value IsStart GroupingSet
0 1 Banana 1 1
1 3 Banana 0 1
3 4 Orange 1 1
4 7 Orange 0 1
7 8 Apple 1 1
8 9 Apple 0 1
9 10 Apple 0 1
10 15 Apple 0 1
20 22 Apple 1 2 -- SECOND NON CONTINUOUS RANGE FOR APPLES
22 23 Apple 0 2
23 28 Banana 1 2 -- SECOND NON CONTINUOUS RANGE FOR BANANAS
28 30 Banana 0 2
最後,您可以通過彙總值分組,而這個標識符列,以確定唯一的組。
您還可以通過擴展每個範圍伸到行通過交叉連結到數表(爲簡便起見我用master..spt_values
)做到這一點:
WITH CTE AS
( SELECT t.[value],
Number = t.Start + v.Number,
GroupingSet = t.Start + v.Number - ROW_NUMBER() OVER(PARTITION BY t.[value] ORDER BY t.Start + v.Number)
FROM @T AS T
INNER JOIN Master..spt_values v
ON v.[Type] = 'P'
AND v.Number < (t.[End] - t.[Start])
)
SELECT Value, [Start] = MIN(Number), [End] = MAX(Number)
FROM CTE
GROUP BY GroupingSet, Value;
這樣做的垮臺是,它很可能是如果你有很多的行/大範圍,那麼內存密集。擴大範圍後,這只是使用使用Itzik Ben-Gan's Gaps and Islands Solutions
這就是爲什麼這個網站仍然是我去的地方。幾個小時後,我有幾個很好的迴應。謝謝大家!我會試着圍繞不同的選項進行包裝,並會很快接受相應的提議。 –
不能同意更多,把我的答案放在一邊,其他人都很棒。 – JiggsJedi
所有好的答案,謝謝!我沒有資格評論各種選擇的優雅/效率,所以我接受了@ adrianm的答案,因爲我可以適應我的需求,他的工作速度最快。 –