1. 程式人生 > >sqlserver 行轉列、字串行轉列、自動生產行轉列指令碼

sqlserver 行轉列、字串行轉列、自動生產行轉列指令碼

行轉列,老生常談的問題。這裡總結一下網上的方法。

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語句生成自動行轉列的指令碼。好動手的童鞋趕快動起來吧。

如果您有疑問,歡迎評論區交流討論