[英]SQL Server get concatenated number ranges (ISLANDS in sequences) from list
我具有以下表結構:
DECLARE @headerTable TABLE (HeaderTableId INT)
INSERT INTO @headerTable VALUES (1), (2), (3)
DECLARE @detailTable TABLE (HeaderTableIdFK INT, DetailTableNumber INT)
INSERT INTO @detailTable VALUES (1,1), (1,2), (1,3), (1,6), (1,7), (1,8)
,(2,51), (2,52), (2,53),(2,100), (2,101), (2,102), (2,200)
,(3,5), (3,6), (3,13),(3,20), (3,30), (3,51), (3,52), (3,53)
我必須獲得以下選擇:
HeaderTableId
, NumberRanges
'1',||||||||||||||||||||||||||| '1-3,6-8'
'2',|||||||||||||||||||||||||| '51 -53、100-102、200'
'3',|||||||||||||||||||||||||| '5-6,13,20,30,51-53'
我寧願在一個select語句中獲得所有內容,而沒有其他臨時表。
謝謝!
;WITH CTE as
(
SELECT HeaderTableIdFK, DetailTableNumber,
DetailTableNumber
- row_number() over (partition by HeaderTableIdFK order by DetailTableNumber) grp
FROM @detailTable
), CTE2 as
(
SELECT HeaderTableIdFK, min(DetailTableNumber) min, max(DetailTableNumber) max
FROM CTE
GROUP BY HeaderTableIdFK, grp
)
SELECT HeaderTableIdFK,
STUFF((
SELECT ', ' + CASE WHEN [min] < [max]
THEN CAST([min] as varchar(18)) + '-' + CAST([max] as varchar(18))
ELSE CAST([min] as varchar(18))
END
FROM CTE2 t1
WHERE t1.HeaderTableIdFK = t.HeaderTableIdFK
for xml path(''), type
).value('.', 'varchar(max)'), 1, 1, '') [NumberRanges]
FROM CTE2 t
GROUP BY t.HeaderTableIdFK
結果:
HeaderTableIdFK NumberRanges
1 1-3, 6-8
2 51-53, 100-102, 200
3 5-6, 13-13, 20-20, 30-30, 51-53
您的問題至少有2種解決方案。
首先,嘗試此處完全描述的“缺口和孤島方法” 。
否則,連接數據時不進行范圍調整,然后應用一些文本參數函數將“ id1,id2,id4”字符串列表轉換為范圍“ id1-2,id4”字符串。 為此,請使用以下查詢,並使用您的text-argument函數對其進行擴展:
DECLARE @headerTable TABLE (HeaderTableId INT)
INSERT INTO @headerTable VALUES (1), (2), (3)
DECLARE @detailTable TABLE (HeaderTableIdFK INT, DetailTableNumber INT)
INSERT INTO @detailTable VALUES
(1,1), (1,2), (1,3), (1,6), (1,7), (1,8)
,(2,51), (2,52), (2,53),(2,100), (2,101), (2,102), (2,200)
,(3,5), (3,6), (3,13),(3,20), (3,30), (3,51), (3,52), (3,53)
SELECT
t1.HeaderTableId
,STUFF(
(SELECT
', ' + cast(t2.DetailTableNumber as varchar(10) )
FROM @detailTable t2
WHERE t1.HeaderTableId = t2.HeaderTableIdFK
ORDER BY t2.DetailTableNumber
FOR XML PATH(''), TYPE
).value('.','varchar(max)')
,1,2, ''
) AS ChildValues
FROM @headerTable t1
GROUP BY t1.HeaderTableId
-----
Output:
1 '1, 2, 3, 6, 7, 8'
2 '51, 52, 53, 100, 101, 102, 200'
3 '5, 6, 13, 20, 30, 51, 52, 53'
另外,您可以嘗試使用Tally表方法 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.