SQL Server查询需求:合并相同F_name与ID的行并转置指定列
在SQL Server中实现行列转置(合并相同F_name和ID的行)
嘿,我来帮你搞定这个SQL Server的数据行列转置需求!咱们先理清楚前后的数据格式:
原始数据表格
| F_name | ID | Type | Result |
|---|---|---|---|
| George | 1 | T-shirt | Y |
| George | 1 | Pants | N |
| George | 2 | Boots | O |
| Dani | 2 | T-shirt | Y |
| Dani | 1 | Boots | Y |
目标输出表格
| F_name | ID | T-shirt | Pants | Boots |
|---|---|---|---|---|
| George | 1 | Y | N | null |
| George | 2 | null | null | O |
| Dani | 2 | Y | null | null |
| Dani | 1 | null | null | Y |
接下来直接上解决方案,分两种场景:如果你的Type类型是固定的几个值,用静态PIVOT就够了;如果Type可能随时新增,那就用动态SQL自动适配。
静态PIVOT方案(固定Type值)
这个方案简单直接,适合Type值确定的场景:
SELECT F_name, ID, [T-shirt] AS T-shirt, [Pants] AS Pants, [Boots] AS Boots FROM ( -- 先获取基础数据,确保只包含需要的列 SELECT F_name, ID, Type, Result FROM YourTableName -- 记得把这里替换成你实际的表名 ) AS SourceTable PIVOT ( -- 因为每个(F_name, ID, Type)组合是唯一的,用MAX/MIN都能拿到正确的Result值 MAX(Result) -- 指定要转成列的Type值 FOR Type IN ([T-shirt], [Pants], [Boots]) ) AS PivotTable -- 排序让结果和目标格式一致 ORDER BY F_name, ID;
简单解释下:
- 子查询
SourceTable就是把我们需要的基础数据捞出来,避免多余列干扰转置。 PIVOT函数是核心:它把Type列里的T-shirt、Pants、Boots这几个值转成单独的列名,用MAX聚合函数填充对应的Result值——因为每个分组下的Type值都是唯一的,MAX和MIN效果完全一样,随便用哪个都行。- 最后用ORDER BY排序,让结果和你想要的格式对齐。
动态SQL方案(Type值不固定)
如果未来可能新增其他类型(比如Jacket、Hat之类的),不想每次都改SQL,就用动态SQL自动生成列:
DECLARE @Columns NVARCHAR(MAX), @SQL NVARCHAR(MAX); -- 自动获取所有不同的Type值,转成带方括号的列名字符串 SELECT @Columns = STRING_AGG(QUOTENAME(Type), ', ') FROM (SELECT DISTINCT Type FROM YourTableName) AS Types; -- 构建完整的动态SQL语句 SET @SQL = N' SELECT F_name, ID, ' + @Columns + N' FROM ( SELECT F_name, ID, Type, Result FROM YourTableName ) AS SourceTable PIVOT ( MAX(Result) FOR Type IN (' + @Columns + N') ) AS PivotTable ORDER BY F_name, ID;'; -- 执行动态生成的SQL EXEC sp_executesql @SQL;
解释下动态方案:
- 先用
STRING_AGG(SQL Server 2017及以上版本支持)把所有不同的Type值拼接成[T-shirt], [Pants], [Boots]这样的格式,自动适配所有Type类型。 - 把这个列名字符串插入到SQL模板里,生成完整的查询语句。
- 最后用
sp_executesql执行动态生成的SQL,这样不管Type有多少种,都能自动生成对应的列,不用手动维护。
内容的提问来源于stack exchange,提问作者Wissam safar
相关产品推荐
相关产品推荐

