2011-09-16 102 views
0

我試圖創建一個查詢到以下信息結合:TSQL合併多行到一行

FileID ErrorCode ErrorDesc    ErrorCount 
    1   4  Bad File Name    3 
    2   6  Bad File Code   56 
    3   4  Bad File Name    2 
    3  12  Line Length Invalid  3 
    3  17  Missing Req Fields  150 

我想基礎上,FileID所有行結合起來,使所有的信息對於一個給定FileID會出現在同一行,如下:

1 4 Bad File Name  3 
2 6 Bad File Code 56 
3 4 Bad File Name  2  12 Line Length Invalid 3  17 Missing Req Fields 150 

我它運行到那裏的問題將給予每個文件錯誤的未知量。它可能有1-50個錯誤,我想將所有這些信息合併到一行中。我不確定這是否可能,或者是否有另一種方法來查看此問題。我的最終目標是最終創建一份關於這些數據的報告。謝謝!

+1

有行對於任何給定的寫到FileID一個最大數量? ErrorCodes的列表是已知的並且是有限的嗎?如果有兩個錯誤12,你需要分別報告他們兩個嗎?無論如何,我建議這個崩潰會在表現層處理得更好。 –

+0

根據錯誤總數將會有最大行數。在這種情況下,有50個錯誤,每個FileID最多有50個條目。所有錯誤代碼在每個給定文件中都是唯一的。所以一個FileID只會列出每個錯誤代碼一次。 – buzzzzjay

+1

如果您發佈代碼,XML或數據樣本,**請**在文本編輯器中突出顯示這些行,然後單擊編輯器工具欄上的「代碼樣本」按鈕(「{}」)以精確地格式化和語法突出顯示它! (並且沒有雜亂的' '和'
'需要,要麼!!) –

回答

3

比的Mikael是一個涉及多一點 - 的主要區別是,列在這裏保持(但是列比第一個「排隊」等每個錯誤代碼)。

設置:

CREATE TABLE dbo.t 
(
    FileID INT, 
    ErrorCode INT, 
    ErrorDesc VARCHAR(255), 
    ErrorCount INT 
); 

INSERT dbo.t VALUES 
(1,4,'Bad File Name',3), 
(2,6,'Bad File Code',56), 
(3,4,'Bad File Name',2), 
(3,12,'Line Length Invalid',3), 
(3,17,'Missing Req Fields',150); 

代碼:

DECLARE 
    @sql0 NVARCHAR(MAX) = N'', 
    @sql1 NVARCHAR(MAX) = N'', 
    @sql2 NVARCHAR(MAX) = N'', 
    @minC INT; 

SELECT @minC = MIN(ErrorCode) FROM dbo.t; 

SELECT @sql1 += REPLACE(',x$.ErrorCode AS Code$, 
    x$.ErrorDesc AS Desc$,x$.ErrorCount AS Count$', 
    '$', CONVERT(VARCHAR(12), ErrorCode)) 
    FROM dbo.t WHERE ErrorCode > @minC GROUP BY ErrorCode ORDER BY ErrorCode; 

SELECT @sql2 += REPLACE(' 
    LEFT OUTER JOIN x AS x$ ON z.FileID = x$.FileID 
    AND x$.ErrorCode = $ 
    AND x$.ErrorCode > z.ErrorCode', '$', CONVERT(VARCHAR(12), ErrorCode)) 
    FROM dbo.t WHERE ErrorCode > @minC GROUP BY ErrorCode ORDER BY ErrorCode; 

SET @sql0 = ';WITH y AS (
    SELECT FileID, ErrorCode, ErrorDesc, ErrorCount, 
     rn = ROW_NUMBER() OVER (PARTITION BY FileID ORDER BY ErrorCode) 
    FROM dbo.t 
), 
z AS (SELECT FileID, ErrorCode, ErrorDesc, ErrorCount FROM y WHERE rn = 1), 
x AS (SELECT FileID, ErrorCode, ErrorDesc, ErrorCount FROM y WHERE rn > 1) 
SELECT z.*' + @sql1 + ' FROM z 
' + @sql2; 

-- PRINT @sql0; -- to see what has been crafted  
EXEC sp_executesql @sql0; 
GO 

清理:

DROP TABLE dbo.t; 
GO 
+1

當然+1。我正在看它,以及...這可能是因爲我正在爲我的孩子做飯,但我不明白。必須坐下來了解一下你在這裏做了什麼:) –

+1

只是一個錨點和一堆左連接。我對此並不滿意,因爲對於任何FileID而言,任何ErrorCode都會出現空列,但不會出現在其他任何級別中。我仍然認爲表現層是應該被處理的地方...... –

+0

令人印象深刻。這正是我想弄清楚的,它很複雜,但非常有趣。謝謝! – buzzzzjay

5
declare @T table (FileID int, ErrorCode int, ErrorDesc varchar(max), ErrorCount int) 

insert into @T values 
(1,    4,     'Bad File Name',   3), 
(2,    6,     'Bad File Code',   56), 
(3,    4,     'Bad File Name',   2), 
(3,    12,     'Line Length Invalid', 3), 
(3,    17,     'Missing Req Fields',  150) 

select FileID, 
     (select cast(ErrorCode as varchar(10))+' '+ErrorDesc+' '+cast(ErrorCount as varchar(10))+' ' 
     from @T as T2 
     where T1.FileID = T2.FileID 
     for xml path(''), type).value('.', 'varchar(max)') 
from @T as T1 
group by FileID 
+0

我想這樣做,而不將它們合併成一列。思考? – buzzzzjay

+0

@buzzzzjay - 請回答亞倫給出的答案。動態是我知道的具有「未知/可變」列數的唯一方法。 –

+0

@buzzzzjay您真的正在爲您自己解決您的問題。 –