• 03. 行列转换写法小结


    行列转换,通常有2种方法,一是CASE WHEN/UNION;一是PIVOT/UNPIVOT。对于行值或列数不固定的情况,需要用动态SQL。


    一. 行转列

    --drop table RowToCol
    create table RowToCol
    (
    ID int,
    Code varchar(10),
    Value int
    )
    Go
    insert RowToCol 
    select 1,'Item1',1000 union all
    select 1,'Item2',1000 union all
    select 1,'Item3',500 union all
    select 2,'Item1',2000 union all
    select 2,'Item2',0 union all
    select 3,'Item1',1000 union all
    select 3,'Item3',500 
    GO
    select * from RowToCol

     要得到这样的结果:

    ID Item1 Item2 Item3
    1 1000 1000 500
    2 2000 0 0
    3 1000 0 500


    1. CASE WHEN
    在SQL Server 2000时,常用的写法,沿用至今。
    (1) 静态

    select ID,
    sum(case Code when 'Item1' then Value else 0 end) as Item1,
    sum(case Code when 'Item2' then Value else 0 end) as Item2,
    sum(case Code when 'Item3' then Value else 0 end) as Item3
    from RowToCol group by ID
    --或者用max也行
    select ID,
    max(case Code when 'Item1' then Value else 0 end) as Item1,
    max(case Code when 'Item2' then Value else 0 end) as Item2,
    max(case Code when 'Item3' then Value else 0 end) as Item3
    from RowToCol group by ID

     (2) 动态

    在不确定有多少行需要转为列时,先distinct出待转列的值,再拼出包含若干个CASE的SQL语句,然后运行。

    declare @sql varchar(8000)
    set @sql = 'select ID '
    select @sql = @sql + ' , max(case Code when ''' + Code + ''' then Value else 0 end) [' + Code + ']'
    from (select distinct Code from RowToCol) as a
    set @sql = @sql + ' from RowToCol group by ID'
    --print @sql
    exec(@sql)

     

    2. PIVOT
    PIVOT是SQL Server 2005的新语法,Oracle在11g中也推出了这个语法。
    (1) 静态

    select * from (select * from RowToCol) a 
    pivot (max(value) for Code in ([Item1],[Item2],[Item3])) b

     (2) 动态

    用PIVOT拼写动态SQL时就简单了,只要把后面的列清单整理出来就可以了。

    declare @sql varchar(8000)
    select @sql = isnull(@sql + '],[' , '') + Code from RowToCol group by Code
    set @sql = '[' + @sql + ']'
    --print @sql
    exec ('select * from (select * from RowToCol) a pivot (max(value) for Code in (' + @sql + ')) b')

     

    二. 列转行

    --drop table ColToRow
    create table ColToRow
    (
    ID int,
    Item1 int,
    Item2 int,
    Item3 int
    )
    GO
    insert into ColToRow
    select '1',1000,1000,500 union all
    select '2',2000,0,0 union all
    select '3',1000,0,500 
    GO
    select * from ColToRow

     要得到这样的结果:

    ID Code Value
    1 Item1 1000
    1 Item2 1000
    1 Item3 500
    2 Item1 2000
    2 Item2 0
    2 Item3 0
    3 Item1 1000
    3 Item2 0
    3 Item3 500

    1. UNION
    在SQL Server 2000时,常用的写法,沿用至今。
    (1) 静态

    select ID,Code='Item1',Value=Item1 from ColToRow
    union all
    select ID,Code='Item2',Value=Item2 from ColToRow
    union all
    select ID,Code='Item3',Value=Item3 from ColToRow
    order by ID

     SQL Server对于多个UNION的排序,只要在最后加ORDER BY就可以了。

    (2) 动态
    在不确定有多少列需要转为行时,先借助系统表syscolumns找出待转行的列,再拼出包含若干个UNION语句,然后运行。

    declare @sql varchar(8000)
    select @sql = isnull(@sql + ' union all ' , '' ) + ' select ID , [Code] = ' + quotename(Name , '''') + ' , [Value] = ' + quotename(Name) + ' from ColToRow'
    from syscolumns 
    where name <> N'ID' and ID = object_id('ColToRow')
    order by colid asc
    --print @sql
    exec(@sql + ' order by ID ')

     

    2. UNPIVOT
    UNPIVOT是SQL Server 2005的新语法,Oracle在11g中也推出了这个语法。
    (1) 静态

    select ID , Code , Value from ColToRow 
    unpivot (Value for Code in([Item1] , [Item2] , [Item3])) t

     (2) 动态

    declare @sql varchar(8000)
    select @sql = isnull(@sql + '],[' , '') + name from syscolumns 
    where name <> N'ID' and ID = object_id('ColToRow')
    set @sql = '[' + @sql + ']'
    --print @sql
    exec('select ID , Code , Value from ColToRow unpivot (Value for Code in(' + @sql + ')) t')

     

     

  • 相关阅读:
    程序员的四个阶段
    2010Year Plans
    HttpHandler HttpModule入门篇
    Lucene.net索引文件的并发访问和线程安全性
    stream流写到MemoryStream内存流引发得问题
    ASP.NET 2.0 多文件上传小经验
    HTML 迷魂灯
    如何在Windows下搭建Android开发环境
    利用Lucene.net搭建站内搜索(4)数据检索
    数据加密和解密
  • 原文地址:https://www.cnblogs.com/seusoftware/p/3238022.html
Copyright © 2020-2023  润新知