行轉列,老生常談的問題。這里總結一下網上的方法。
1、生成測試數據:
CREATE TABLE human( name NVARCHAR(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')
查詢數據:
注意:這里的score是數值類型列,而grade是字符串類型的列
2、利用case when 語句完成行轉列,其中行轉列之后的列的屬性是數值類型
SELECT name, 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 技術 FROM dbo.human GROUP BY name
結果:
3、利用case when 語句完成行轉列,其中行轉列之后的列的屬性是字符串類型
又分為兩種情況,a:是借用for xml path 拼接字符串,b:巧妙的借用max()函數可以對字符串進行運算的特點進行篩選
a:借用for xml path 拼接字符串
SELECT name , ( SELECT grade + '' FROM dbo.human WHERE name = a.name AND norm = '考勤' FOR XML PATH('') ) AS 考勤 , ( SELECT grade + '' FROM dbo.human WHERE name = a.name AND norm = '生產' FOR XML PATH('') ) AS 生產 , ( SELECT grade + '' FROM dbo.human WHERE name = a.name AND norm = '技術' FOR XML PATH('') ) AS 技術 FROM dbo.human a GROUP BY name;
結果:
b:巧妙的借用max()(或min())函數可以對字符串進行運算的特點進行篩選
SELECT name , 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 技術 FROM dbo.human a GROUP BY name;
結果:
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 DISTINCT norm FROM dbo.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語句:
完美!拼接的語句正式我們所希望的,所以結果也不出所料:
4、pivot新特性實現行轉列,針對行轉列后,列的屬性是數值類型的情況,這里指score
SELECT * FROM ( SELECT name , norm , score FROM dbo.human ) t PIVOT( SUM(score) FOR norm IN ( 考勤, 生產, 技術 ) ) AS pvt;
結果:
5、pivot新特性實現行轉列,針對行轉列后,列的屬性是字符串類型的情況,這里指score
SELECT * FROM ( SELECT name , norm , grade FROM dbo.human ) t PIVOT( MAX(grade) FOR norm IN ( 考勤, 生產, 技術 ) ) AS pvt;
6、同理,我們也可以通過拼接字符串的形式來組織pivot語句生成自動行轉列的腳本。好動手的童鞋趕快動起來吧。
如果您有疑問,歡迎評論區交流討論