处理表格数据时,通常需要根据一个或多个列对记录进行分组,并将结果合并到具有多个列的单行中。在处理与每个组关联的多个值时,这尤其有用。
假设您有一个包含测试结果的表,其中每一行代表一种特定的测试类型及其对应的结果。例如,“结果”表可能具有以下模式:
CREATE TABLE Result( WorkOrder varchar(10), TestType varchar(20), Result decimal(10,2) );
以及以下数据:
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)
为了按“TestType”对这些结果进行分组,并为每个结果创建具有多个列的新行,我们可以使用“交叉表”或“透视”操作。一种方法是使用“ROW_NUMBER”函数为组内的每个结果分配顺序号,然后使用条件聚合来提取所需的值。
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>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>
但是,这种方法仅限于固定数量的结果。为了创建一个可以容纳任意数量结果的动态解决方案,我们可以使用一种称为“交叉应用计数表”的技术。
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;
此查询使用“计数表”创建一个整数序列,根据表中结果的最大数量动态生成 SQL 语句。此技术允许将任意数量的结果合并到单行中。
通过使用这些方法,您可以有效地将表格数据分组和合并为更结构化和更有意义的格式,从而简化数据分析和可视化。
以上是如何在SQL中动态分组和合并多行多列?的详细内容。更多信息请关注PHP中文网其他相关文章!