sqlserver|sqlserver sql行专列_sqlserver 行转列、字符串行转列、自动生产行转列脚本

【sqlserver|sqlserver sql行专列_sqlserver 行转列、字符串行转列、自动生产行转列脚本】行转列,老生常谈的问题。这里总结一下网上的方法。
1、生成测试数据:
CREATE TABLEhuman(
nameNVARCHAR(5), --姓名
norm NVARCHAR(5), --指标
score INT , --分数
grade NVARCHAR(2) --等级
)GO
INSERT INTO human(name,norm,score,grade)VALUES('旺仔','考勤',56,'c'),
('旺仔','生产',85,'b'),
('旺仔','技术',95,'a'),
('小杰','考勤',66,'a'),
('小杰','生产',77,'b'),
('小杰','技术',88,'c'),
('玉红','考勤',92,'j'),
('玉红','生产',73,'k'),
('玉红','技术',81,'m')
查询数据:
sqlserver|sqlserver sql行专列_sqlserver 行转列、字符串行转列、自动生产行转列脚本
文章图片

注意:这里的score是数值类型列,而grade是字符串类型的列
2、利用case when 语句完成行转列,其中行转列之后的列的属性是数值类型
SELECTname,SUM(CASE WHEN norm = '考勤' THEN score ELSE 0 END) AS考勤,SUM(CASE WHEN norm = '生产' THEN score ELSE 0 END) AS生产,SUM(CASE WHEN norm = '技术' THEN score ELSE 0 END) AS技术FROMdbo.humanGROUP BY name
结果:
sqlserver|sqlserver sql行专列_sqlserver 行转列、字符串行转列、自动生产行转列脚本
文章图片

3、利用case when 语句完成行转列,其中行转列之后的列的属性是字符串类型
又分为两种情况,a:是借用for xml path 拼接字符串,b:巧妙的借用max()函数可以对字符串进行运算的特点进行筛选
a:借用for xml path 拼接字符串
SELECTname ,
(SELECT grade + ''
FROMdbo.humanWHERE name =a.nameAND norm = '考勤'
FORXML PATH('')
)AS考勤 ,
(SELECT grade + ''
FROMdbo.humanWHERE name =a.nameAND norm = '生产'
FORXML PATH('')
)AS生产 ,
(SELECT grade + ''
FROMdbo.humanWHERE name =a.nameAND norm = '技术'
FORXML PATH('')
)AS技术FROMdbo.human aGROUP BY name;
结果:
sqlserver|sqlserver sql行专列_sqlserver 行转列、字符串行转列、自动生产行转列脚本
文章图片

b:巧妙的借用max()(或min())函数可以对字符串进行运算的特点进行筛选
SELECTname ,MAX( CASE WHEN a.norm = '考勤' THEN a.grade ELSE '' END ) AS考勤,MAX( CASE WHEN a.norm = '生产' THEN a.grade ELSE '' END ) AS生产,MAX( CASE WHEN a.norm = '技术' THEN a.grade ELSE '' END ) AS技术FROMdbo.human aGROUP BY name;
结果:
sqlserver|sqlserver sql行专列_sqlserver 行转列、字符串行转列、自动生产行转列脚本
文章图片

3、实际生产过程中会碰到这种情况:norm列的值有很多种情况,比如几十、上百个,难道我们一一手写吗?不,我们可以考虑使用拼接字符串的方式,动态实现行转列
DECLARE @sql NVARCHAR(MAX); SELECT @sql = 'select name,'; SELECT @sql = @sql + 'max(case when a.norm =''' +a.norm+ '''then a.grade ELSE''''END' + ') as' + QUOTENAME(a.norm) + ','
FROM ( SELECT DISTINCTnormFROMdbo.human
) a; SELECT @sql = SUBSTRING(@sql, 1, LEN(@sql) - 3); SELECT @sql = @sql + 'FROM dbo.human a
GROUP BY name; '; SELECT @sql; EXEC (@sql);
首先观察一下我们自动拼接出来的sql语句:
sqlserver|sqlserver sql行专列_sqlserver 行转列、字符串行转列、自动生产行转列脚本
文章图片

完美!拼接的语句正式我们所希望的,所以结果也不出所料:
sqlserver|sqlserver sql行专列_sqlserver 行转列、字符串行转列、自动生产行转列脚本
文章图片

4、pivot新特性实现行转列,针对行转列后,列的属性是数值类型的情况,这里指score
SELECT *
FROM ( SELECTname ,
norm ,
scoreFROMdbo.human
) t PIVOT(SUM(score) FOR norm IN ( 考勤, 生产, 技术 ) ) AS pvt;
结果:
sqlserver|sqlserver sql行专列_sqlserver 行转列、字符串行转列、自动生产行转列脚本
文章图片

5、pivot新特性实现行转列,针对行转列后,列的属性是字符串类型的情况,这里指score
SELECT *
FROM ( SELECTname ,
norm ,
gradeFROMdbo.human
) t PIVOT(MAX(grade) FOR norm IN ( 考勤, 生产, 技术 ) ) AS pvt;
sqlserver|sqlserver sql行专列_sqlserver 行转列、字符串行转列、自动生产行转列脚本
文章图片

6、同理,我们也可以通过拼接字符串的形式来组织pivot语句生成自动行转列的脚本。好动手的童鞋赶快动起来吧。
如果您有疑问,欢迎评论区交流讨论

    推荐阅读