sqlserver 行轉列、字串行轉列、自動生產行轉列指令碼
阿新 • • 發佈:2018-12-06
行轉列,老生常談的問題。這裡總結一下網上的方法。
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 WHENnorm = '生產' 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語句生成自動行轉列的指令碼。好動手的童鞋趕快動起來吧。
如果您有疑問,歡迎評論區交流討論