SQL多行列转单行求助:实现多Temp列的Pivot聚合
解决多行多列转单行多列的SQL方案
针对你需要将Time、Source、Temp1-Temp4结构转成每行对应一个Time、每个Source对应一组SrcX_TempY列的需求,下面提供两种实用方案,解决你用Pivot无法同时处理多个聚合函数的问题:
方案一:条件聚合(最直观,适合固定数量的Source/Temp列)
直接通过CASE WHEN结合聚合函数生成目标列,逻辑简单易维护:
SELECT Time, -- Src1对应的温度列 MAX(CASE WHEN Source = 'Src1' THEN Temp1 END) AS Src1_Temp1, MAX(CASE WHEN Source = 'Src1' THEN Temp2 END) AS Src1_Temp2, MAX(CASE WHEN Source = 'Src1' THEN Temp3 END) AS Src1_Temp3, MAX(CASE WHEN Source = 'Src1' THEN Temp4 END) AS Src1_Temp4, -- Src2对应的温度列 MAX(CASE WHEN Source = 'Src2' THEN Temp1 END) AS Src2_Temp1, MAX(CASE WHEN Source = 'Src2' THEN Temp2 END) AS Src2_Temp2, MAX(CASE WHEN Source = 'Src2' THEN Temp3 END) AS Src2_Temp3, MAX(CASE WHEN Source = 'Src2' THEN Temp4 END) AS Src2_Temp4 -- 如果有更多Source,继续添加对应CASE语句 FROM YourTableName GROUP BY Time ORDER BY Time;
说明:
- 用
MAX是因为每个Time+Source组合仅对应一行数据,MAX/AVG/MIN都能拿到唯一值,选MAX是习惯用法,避免NULL干扰。 - 若源数据中
Time+Source可能重复,MAX会保留非空的最大值,符合多数场景需求。
方案二:UNPIVOT+PIVOT组合(灵活适配动态列)
先将Temp1-Temp4转成键值对,再拼接Source生成目标列名,最后透视回单行结构:
SELECT Time, Src1_Temp1, Src1_Temp2, Src1_Temp3, Src1_Temp4, Src2_Temp1, Src2_Temp2, Src2_Temp3, Src2_Temp4 FROM ( -- 第一步:将Temp列转成行,生成新的列名(Source_TempX) SELECT Time, CONCAT(Source, '_', TempType) AS ColumnName, TempValue FROM YourTableName UNPIVOT ( TempValue FOR TempType IN (Temp1, Temp2, Temp3, Temp4) ) AS UnpivotTemp ) AS PivotSource -- 第二步:将拼接后的列名透视回表头 PIVOT ( MAX(TempValue) FOR ColumnName IN ( Src1_Temp1, Src1_Temp2, Src1_Temp3, Src1_Temp4, Src2_Temp1, Src2_Temp2, Src2_Temp3, Src2_Temp4 ) ) AS PivotResult ORDER BY Time;
说明:
- UNPIVOT解决了Pivot只能处理单个聚合列的问题,先把多列Temp转成单行列,再和Source组合成唯一的目标列名。
- 若Source的取值不固定(比如有很多不同的SrcX),可以用动态SQL自动生成列,避免手动维护:
DECLARE @Columns NVARCHAR(MAX), @SQL NVARCHAR(MAX); -- 自动生成所有目标列名 SELECT @Columns = STRING_AGG( CONCAT('[', Source, '_', TempType, ']'), ', ' ) FROM ( SELECT DISTINCT Source FROM YourTableName ) AS Sources CROSS JOIN ( SELECT 'Temp1' AS TempType UNION ALL SELECT 'Temp2' UNION ALL SELECT 'Temp3' UNION ALL SELECT 'Temp4' ) AS TempTypes; -- 拼接并执行动态SQL SET @SQL = CONCAT(' SELECT Time, ', @Columns, ' FROM ( SELECT Time, CONCAT(Source, ''_'', TempType) AS ColumnName, TempValue FROM YourTableName UNPIVOT ( TempValue FOR TempType IN (Temp1, Temp2, Temp3, Temp4) ) AS UnpivotTemp ) AS PivotSource PIVOT ( MAX(TempValue) FOR ColumnName IN (', @Columns, ') ) AS PivotResult ORDER BY Time;'); EXEC sp_executesql @SQL;
内容的提问来源于stack exchange,提问作者JoeyD
相关产品推荐
相关产品推荐

