處理表格資料時,通常需要根據一個或多個欄位對記錄進行分組,並將結果合併到具有多個欄位的單行中。在處理與每個群組關聯的多個值時,這尤其有用。
假設您有一個包含測試結果的表,其中每一行代表一種特定的測試類型及其對應的結果。例如,「結果」表可能具有以下模式:
<code class="language-sql">CREATE TABLE Result( WorkOrder varchar(10), TestType varchar(20), Result decimal(10,2) );</code>
以及以下數據:
<code class="language-sql">INSERT INTO Result (WorkOrder, TestType, Result) VALUES ('HP19002316','VitaminA', 10.3), ('HP19002316','VitaminA', 11.3), ('HP19002316','VitaminA', 12.3), ('HP19002316','VitaminB', 13.4), ('HP19002316','VitaminB', 14.4), ('HP19002316','VitaminC', 15.5), ('HP19002316','VitaminD', 17.0)</code>
為了按「TestType」對這些結果進行分組,並為每個結果建立具有多個列的新行,我們可以使用「交叉表」或「透視」操作。一種方法是使用“ROW_NUMBER”函數為群組內的每個結果分配順序號,然後使用條件聚合來提取所需的值。
<code class="language-sql">WITH RNs AS( SELECT WorkOrder, TestType, Result, ROW_NUMBER() OVER (PARTITION BY WorkOrder, TestType ORDER BY (SELECT NULL)) AS RN FROM dbo.Result) SELECT WorkOrder, TestType, MAX(CASE RN WHEN 1 THEN Result END) AS Result1, MAX(CASE RN WHEN 2 THEN Result END) AS Result2, MAX(CASE RN WHEN 3 THEN Result END) AS Result3 FROM RNs R GROUP BY WorkOrder, TestType;</code>
此查詢將產生以下輸出:
<code>WorkOrder TestType Result1 Result2 Result3 ========================================================== HP19002316 VitaminA 10.3 11.3 12.3 HP19002316 VitaminB 13.4 14.4 NULL HP19002316 VitaminC 15.5 NULL NULL HP19002316 VitaminD 17.0 NULL NULL</code>
但是,這種方法僅限於固定數量的結果。為了創建一個可以容納任意數量結果的動態解決方案,我們可以使用一種稱為「交叉應用計數表」的技術。
<code class="language-sql">DECLARE @SQL nvarchar(MAX), @CRLF nchar(2) = NCHAR(13) + NCHAR(10), @MaxTally int; SELECT @MaxTally = MAX(C) FROM (SELECT COUNT(*) AS C FROM dbo.Result GROUP BY WorkOrder, TestType) R; WITH N AS( SELECT N FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)), Tally AS( SELECT TOP (@MaxTally) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I FROM N N1, N N2) SELECT @SQL = N'WITH RNs AS(' + @CRLF + N' SELECT WorkOrder,' + @CRLF + N' TestType,' + @CRLF + N' Result,' + @CRLF + N' ROW_NUMBER() OVER (PARTITION BY WorkOrder, TestType ORDER BY (SELECT NULL)) AS RN --ORDER BY 应为您的 ID/始终递增列' + @CRLF + N' FROM dbo.Result)' + @CRLF + N'SELECT WorkOrder,' + @CRLF + N' TestType,' + @CRLF + --由于不知道 SQL Server 版本,因此使用 FOR XML PATH STUFF((SELECT N',' + @CRLF + CONCAT(N' MAX(CASE RN WHEN ',T.I,N' THEN Result END) AS Result',T.I) FROM Tally T ORDER BY T.I ASC FOR XML PATH(N''),TYPE).value('(./text())[1]','nvarchar(MAX)'),1,3,N'') + @CRLF + N'FROM RNs R' + @CRLF + N'GROUP BY WorkOrder,' + @CRLF + N' TestType;'; PRINT @SQL; --您的好朋友。 EXEC sys.sp_executesql @SQL;</code>
此查詢使用「計數表」建立整數序列,根據表中結果的最大數量動態產生 SQL 語句。此技術允許將任意數量的結果合併到單行中。
透過使用這些方法,您可以有效地將表格資料分組和合併為更結構化和更有意義的格式,從而簡化資料分析和視覺化。
以上是如何在SQL中動態分組和合併多行多列?的詳細內容。更多資訊請關注PHP中文網其他相關文章!