Sql server SQL concat整数并将其分组为从到

Sql server SQL concat整数并将其分组为从到,sql-server,tsql,Sql Server,Tsql,我是stackoverflow的新手,但我的问题一直没有解决 我有一个SQL表,它看起来像这样: +-------+------------+ | col1 | col2 | +-------+------------+ | 1 | 1 | | 1 | 2 | | 1 | 3 | | 1 | 4 | | 1 | 6 | +-------+--------

我是stackoverflow的新手,但我的问题一直没有解决

我有一个SQL表,它看起来像这样:

+-------+------------+
| col1  |   col2     |
+-------+------------+
|   1   |     1      |
|   1   |     2      |
|   1   |     3      |
|   1   |     4      |
|   1   |     6      |
+-------+------------+
我不知道如何获得以下结果集:

+-------+------------+
| col1  |SerialNumber|
+-------|------------+
|   1   | 1 to 4, 6  |
+--------------------+
使用XML路径,我可以得到以下结果:

+-------+------------+
| col1  |SerialNumber|
+-------|------------+
|   1   | 1,2,3,4,6, |
+--------------------+
这是我对它的查询:

SELECT DISTINCT O.Col1, 
 (SELECT CAST(P.Col2 As varchar(5)) + ',' AS [text()] 
 FROM #Test P 
 WHERE P.Col1 = O.Col1 
 ORDER BY P.Col1 
 FOR XML PATH('')) AS 'SerialNumber'
 FROM #Test O
如果我的问题已经被问到了,我很抱歉。我也缺少这个主题的关键词。

测试数据:

CREATE TABLE t(col1 int,col2 int)

INSERT t(col1,col2)VALUES
(1,1),(1,2),(1,3),(1,4),
(1,6),(1,7),(1,8),(1,9),
(1,11),
(1,13),

(2,3),(2,4),(2,5),
(2,7)
XML路径的变量为

SELECT col1,col2,outVal
INTO #temp
FROM
  (
    SELECT
      col1,
      col2,
      outVal,
      ISNULL(LEAD(outVal)OVER(PARTITION BY col1 ORDER BY col2),'') nextOutVal
    FROM
      (
        SELECT
          col1,
          col2,
          CASE
            WHEN col2-1=LAG(col2)OVER(PARTITION BY col1 ORDER BY col2) AND col2+1=LEAD(col2)OVER(PARTITION BY col1 ORDER BY col2)
            THEN 'to'
            ELSE CAST(col2 AS varchar(10))
          END outVal
        FROM t
      ) q
  ) q
WHERE outVal<>nextOutVal
ORDER BY col1,col2

SELECT
  t1.col1,
  REPLACE(STUFF(
    (
      SELECT ','+t2.outVal
      FROM #temp t2
      WHERE t2.col1=t1.col1
      ORDER BY t2.col2
      FOR XML PATH('')
    ),1,1,''),',to,',' to ') SerialNumber
FROM (SELECT DISTINCT col1 FROM #temp) t1

DROP TABLE #temp
结果:

col1  SerialNumber
1     1 to 4,6 to 9,11,13
2     3 to 5,7

解决方案:

-- Table creation
CREATE TABLE #ValuesTable (
    Col1 int,
    Col2 int
)
INSERT INTO #ValuesTable VALUES (1, 1)
INSERT INTO #ValuesTable VALUES (1, 2)
INSERT INTO #ValuesTable VALUES (1, 3)
INSERT INTO #ValuesTable VALUES (1, 4)
INSERT INTO #ValuesTable VALUES (1, 6)
INSERT INTO #ValuesTable VALUES (2, 1)
INSERT INTO #ValuesTable VALUES (2, 2)  
INSERT INTO #ValuesTable VALUES (2, 3)
INSERT INTO #ValuesTable VALUES (2, 4)
INSERT INTO #ValuesTable VALUES (2, 6)
INSERT INTO #ValuesTable VALUES (2, 7);
INSERT INTO #ValuesTable VALUES (2, 10);

-- Find sequences
WITH 
TableStart AS (
    SELECT t.Col1, t.Col2, ROW_NUMBER() OVER (ORDER BY t.Col1, t.Col2) AS RN
    FROM #ValuesTable t
    LEFT JOIN #ValuesTable b ON (t.Col1 = b.Col1) AND (t.Col2 = b.Col2 + 1)
    WHERE (b.Col2 IS NULL)
), 
TableEnd AS (
    SELECT t.Col1, t.Col2, ROW_NUMBER() OVER (ORDER BY t.Col1, t.Col2) AS RN
    FROM #ValuesTable t
    LEFT JOIN #ValuesTable b ON (t.Col1 = b.Col1) AND (t.Col2 = b.Col2 - 1)
    WHERE (b.Col2 IS NULL)
), 
TableSequences AS (
    SELECT 
        TableStart.Col1 AS Col1, 
        CASE 
            WHEN (TableStart.Col2 <> TableEnd.Col2) THEN CONVERT(nvarchar(max), TableStart.Col2) + N' to ' + CONVERT(nvarchar(max), TableEnd.Col2)
            ELSE CONVERT(nvarchar(max), TableStart.Col2) 
        END AS Sequence
    FROM TableStart
    LEFT JOIN TableEnd ON (TableStart.RN = TableEnd.RN)
)
-- Select with group concatenation
SELECT
    t1.Col1,
    (
    SELECT t2.Sequence + N', '
    FROM TableSequences t2
    WHERE t2.Col1 = t1.Col1
    ORDER BY t2.Col1
    FOR XML PATH('')
    ) SerialNumber
FROM (SELECT DISTINCT Col1 FROM TableSequences) t1
使用CTE作为每个序列和组串联的起始值和结束值的另一种可能方法:

T-SQL:

-- Table creation
CREATE TABLE #ValuesTable (
    Col1 int,
    Col2 int
)
INSERT INTO #ValuesTable VALUES (1, 1)
INSERT INTO #ValuesTable VALUES (1, 2)
INSERT INTO #ValuesTable VALUES (1, 3)
INSERT INTO #ValuesTable VALUES (1, 4)
INSERT INTO #ValuesTable VALUES (1, 6)
INSERT INTO #ValuesTable VALUES (2, 1)
INSERT INTO #ValuesTable VALUES (2, 2)  
INSERT INTO #ValuesTable VALUES (2, 3)
INSERT INTO #ValuesTable VALUES (2, 4)
INSERT INTO #ValuesTable VALUES (2, 6)
INSERT INTO #ValuesTable VALUES (2, 7);
INSERT INTO #ValuesTable VALUES (2, 10);

-- Find sequences
WITH 
TableStart AS (
    SELECT t.Col1, t.Col2, ROW_NUMBER() OVER (ORDER BY t.Col1, t.Col2) AS RN
    FROM #ValuesTable t
    LEFT JOIN #ValuesTable b ON (t.Col1 = b.Col1) AND (t.Col2 = b.Col2 + 1)
    WHERE (b.Col2 IS NULL)
), 
TableEnd AS (
    SELECT t.Col1, t.Col2, ROW_NUMBER() OVER (ORDER BY t.Col1, t.Col2) AS RN
    FROM #ValuesTable t
    LEFT JOIN #ValuesTable b ON (t.Col1 = b.Col1) AND (t.Col2 = b.Col2 - 1)
    WHERE (b.Col2 IS NULL)
), 
TableSequences AS (
    SELECT 
        TableStart.Col1 AS Col1, 
        CASE 
            WHEN (TableStart.Col2 <> TableEnd.Col2) THEN CONVERT(nvarchar(max), TableStart.Col2) + N' to ' + CONVERT(nvarchar(max), TableEnd.Col2)
            ELSE CONVERT(nvarchar(max), TableStart.Col2) 
        END AS Sequence
    FROM TableStart
    LEFT JOIN TableEnd ON (TableStart.RN = TableEnd.RN)
)
-- Select with group concatenation
SELECT
    t1.Col1,
    (
    SELECT t2.Sequence + N', '
    FROM TableSequences t2
    WHERE t2.Col1 = t1.Col1
    ORDER BY t2.Col1
    FOR XML PATH('')
    ) SerialNumber
FROM (SELECT DISTINCT Col1 FROM TableSequences) t1
注意事项:

-- Table creation
CREATE TABLE #ValuesTable (
    Col1 int,
    Col2 int
)
INSERT INTO #ValuesTable VALUES (1, 1)
INSERT INTO #ValuesTable VALUES (1, 2)
INSERT INTO #ValuesTable VALUES (1, 3)
INSERT INTO #ValuesTable VALUES (1, 4)
INSERT INTO #ValuesTable VALUES (1, 6)
INSERT INTO #ValuesTable VALUES (2, 1)
INSERT INTO #ValuesTable VALUES (2, 2)  
INSERT INTO #ValuesTable VALUES (2, 3)
INSERT INTO #ValuesTable VALUES (2, 4)
INSERT INTO #ValuesTable VALUES (2, 6)
INSERT INTO #ValuesTable VALUES (2, 7);
INSERT INTO #ValuesTable VALUES (2, 10);

-- Find sequences
WITH 
TableStart AS (
    SELECT t.Col1, t.Col2, ROW_NUMBER() OVER (ORDER BY t.Col1, t.Col2) AS RN
    FROM #ValuesTable t
    LEFT JOIN #ValuesTable b ON (t.Col1 = b.Col1) AND (t.Col2 = b.Col2 + 1)
    WHERE (b.Col2 IS NULL)
), 
TableEnd AS (
    SELECT t.Col1, t.Col2, ROW_NUMBER() OVER (ORDER BY t.Col1, t.Col2) AS RN
    FROM #ValuesTable t
    LEFT JOIN #ValuesTable b ON (t.Col1 = b.Col1) AND (t.Col2 = b.Col2 - 1)
    WHERE (b.Col2 IS NULL)
), 
TableSequences AS (
    SELECT 
        TableStart.Col1 AS Col1, 
        CASE 
            WHEN (TableStart.Col2 <> TableEnd.Col2) THEN CONVERT(nvarchar(max), TableStart.Col2) + N' to ' + CONVERT(nvarchar(max), TableEnd.Col2)
            ELSE CONVERT(nvarchar(max), TableStart.Col2) 
        END AS Sequence
    FROM TableStart
    LEFT JOIN TableEnd ON (TableStart.RN = TableEnd.RN)
)
-- Select with group concatenation
SELECT
    t1.Col1,
    (
    SELECT t2.Sequence + N', '
    FROM TableSequences t2
    WHERE t2.Col1 = t1.Col1
    ORDER BY t2.Col1
    FOR XML PATH('')
    ) SerialNumber
FROM (SELECT DISTINCT Col1 FROM TableSequences) t1

在SQL Server 2005、2012、2016上进行了测试。

因此,这基本上是一个缺口和孤岛问题,再加上字符串聚合。您可能需要先搜索“间隙和孤岛”。谢谢,间隙和孤岛描述了我的问题。我缺少关键字。您使用什么版本的SQLServer?我们使用MSSQL 2016。