Проблема в преобразовании столбца строки - PullRequest
1 голос
/ 20 июня 2011

Введите

ID  RowID   Data
1   1   S
1   1   Q
1   1   L
1   1   Null
1   1   Null
1   1   S
1   1   E
1   1   R
1   1   V
1   1   E
1   1   R
1   1   Null
1   1   DB
1   2   S
1   2   T
1   2   A
1   2   C
1   2   K
2   1   O
2   1   V
2   1   E
2   1   R
2   1   Null
2   1   Null
2   1   Null
2   1   F
2   1   L
2   1   O
2   1   W

Ожидаемый результат

ID  NewData
1   SQL2SERVER1DB,STACK
2   OVER3FLOW

1 Ответ

1 голос
/ 20 июня 2011

Единственный способ гарантировать порядок вывода - добавить столбец, который определяет правильный порядок в таблице - я использовал столбец IDENTITY.

Я также предположил, что в вашем примере сценария создания данных есть ошибка (см. Мой комментарий к вопросу) - пересмотренный сценарий создания образца данных выглядит следующим образом:

DECLARE @t TABLE(ID INT IDENTITY(1,1) , groupId  INT, RowID INT, Data VARCHAR(10))
INSERT INTO @t (groupId, RowID,DATA)
SELECT 1,1,'S' UNION ALL SELECT 1,1,'Q' UNION ALL SELECT 1,1,'L' UNION ALL
SELECT 1,1,NULL UNION ALL SELECT 1,1,NULL UNION ALL SELECT 1,1,'S' UNION ALL
SELECT 1,1,'E' UNION ALL SELECT 1,1,'R' UNION ALL SELECT 1,1,'V' UNION ALL SELECT 1,1,'E' UNION ALL
SELECT 1,1,'R' UNION ALL SELECT 1,1,NULL UNION ALL SELECT 1,1,'DB' UNION ALL
SELECT 1,2,'S' UNION ALL SELECT 1,2,'T' UNION ALL SELECT 1,2,'A' UNION ALL SELECT 1,2,'C' UNION ALL
SELECT 1,2,'K' UNION ALL SELECT 2,1,'O' UNION ALL SELECT 2,1,'V' UNION ALL SELECT 2,1,'E' UNION ALL 
SELECT 2,1,'R'  UNION ALL SELECT 2,1,NULL UNION ALL SELECT 2,1,NULL UNION ALL SELECT 2,1,NULL
UNION ALL SELECT 2,1,'F' UNION ALL SELECT 2,1,'L' UNION ALL SELECT 2,1,'O' UNION ALL SELECT 2,1,'W'

Насколько я понимаю, невозможно правильно объединить строки NULL и объединить строки за один шаг, поэтому в этом решении используются цепочечные CTE для выполнения шагов по одному за раз. Я также использовал CTE для дедупликации вывода (а не для группировки).

--convert consecutive nulls to a count
;WITH nullCTE
AS
(
    SELECT ID, ID AS e
    FROM @t AS t
    WHERE t.Data IS NULL
    AND EXISTS (SELECT 1 FROM @t AS q WHERE q.Data IS NOT NULL AND q.Id = t.ID + 1)

    UNION ALL

    SELECT  c.ID, t.Id
    FROM    @t AS t
    JOIN    nullCTE AS c
    ON      t.ID = c.e - 1
    WHERE t.Data IS NULL
)
-- simplify the null table
,grpCTE
AS
(SELECT ID, ID - e + 1 SIZE,
    ROW_NUMBER() OVER (PARTITION BY ID
                       ORDER BY e
                      ) AS rn
 FROM nullCTE
)
--build the output
,outputCTE
AS
(
    SELECT  t1.groupId,
            (
                SELECT COALESCE(t.Data,CAST(g.size AS VARCHAR(11)),'') + CASE WHEN u.RowID > t.RowID AND u.groupId = t.groupId THEN ',' ELSE '' END
                FROM        @t AS t
                LEFT JOIN   grpCTE  AS g
                ON          g.ID = t.ID
                AND         rn = 1
                LEFT JOIN   @t AS u
                ON          u.ID = t.Id + 1
                WHERE t.groupID = t1.groupId
                ORDER BY t.Id
                FOR XML PATH('') 
            ) AS NewData,
            ROW_NUMBER() OVER (PARTITION BY groupId
                               ORDER BY Id
                              ) AS rn
    FROM @t AS t1
)
SELECT groupId, NewData
FROM outputCTE
WHERE rn = 1
...