簡體   English   中英

SQL Server從列表中獲取串聯的數字范圍(序列中的ISLANDS)

[英]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)

我必須獲得以下選擇:

HeaderTableIdNumberRanges

'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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM