2011-06-20 59 views
1

輸入問題在排列變換

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

源表中沒有任何內容可以指示行的順序。您需要一個控制顯示順序的每行標識符 - 可能是一個'IDENTITY'列。 –

+0

您的輸入數據(問題頂部)與示例數據創建腳本不匹配(STACK的''A','C'和'K'在數據中的rowID爲2,但是1腳本,哪一個是正確的? –

回答

1

來保證輸出的順序的唯一方式是增加其定義了正確的順序表中的列 - 我使用了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