SQL Server中如何将一个表的字段值作为新表的列名?
解决SQL透视非数值字段及动态列的问题
1. 非数值字段的聚合处理
要实现同一城市的员工按行展示,直接用普通聚合函数会丢失数据,核心思路是先给每个城市下的员工分配行号,再基于行号做透视:
- 通过
ROW_NUMBER()窗口函数,按City分组给员工编序号,每个城市的员工会得到1、2、3...的唯一编号 - 透视时用
MAX()(或MIN(),因为同一行号+城市对应的员工名是唯一的)作为聚合函数,就能正确提取每个位置的员工名
示例基础SQL(静态列场景):
-- 生成带行号的中间表 WITH RankedEmployees AS ( SELECT EmployeeName, City, ROW_NUMBER() OVER (PARTITION BY City ORDER BY EmployeeName) AS RowNum FROM YourTableName ) -- 执行透视转换 SELECT [Chicago], [LA], [NYC] FROM RankedEmployees PIVOT ( MAX(EmployeeName) -- 利用MAX聚合唯一值,确保每个位置的员工名被正确提取 FOR City IN ([Chicago], [LA], [NYC]) ) AS PivotTable;
2. 动态生成所有城市列
当城市数量过多无法手动列写时,用动态SQL自动获取所有城市名并拼接成透视列:
DECLARE @CityList NVARCHAR(MAX); DECLARE @DynamicSQL NVARCHAR(MAX); -- 第一步:获取所有唯一城市名,拼接成[城市1],[城市2]的格式 SELECT @CityList = STRING_AGG(QUOTENAME(City), ', ') FROM (SELECT DISTINCT City FROM YourTableName) AS UniqueCities; -- 第二步:拼接完整的动态透视SQL SET @DynamicSQL = N' WITH RankedEmployees AS ( SELECT EmployeeName, City, ROW_NUMBER() OVER (PARTITION BY City ORDER BY EmployeeName) AS RowNum FROM YourTableName ) SELECT ' + @CityList + ' FROM RankedEmployees PIVOT ( MAX(EmployeeName) FOR City IN (' + @CityList + ') ) AS PivotTable;'; -- 执行动态SQL语句 EXEC sp_executesql @DynamicSQL;
兼容低版本SQL Server说明
如果使用SQL Server 2017之前的版本,STRING_AGG()不被支持,可改用FOR XML PATH拼接城市列表:
SELECT @CityList = STUFF((SELECT ', ' + QUOTENAME(City) FROM (SELECT DISTINCT City FROM YourTableName) AS UniqueCities FOR XML PATH('')), 1, 2, '');
- 行号排序用
EmployeeName是为了让员工名排列有序,你也可以根据需求替换成其他排序字段(比如入职日期等)
内容的提问来源于stack exchange,提问作者ana996
相关产品推荐
相关产品推荐

