zoukankan      html  css  js  c++  java
  • sql server行转列 列转行交叉表实现[转]

    主要应用case语句来解决行转列的问题
    行转列问题主要分为两类

    1)简单的行转列问题:

    示例表:

    id sid           course result

    1   2005001 语文     80.0
    2   2005001 数学     90.0
    3   2005001 英语     80.0
    4   2005002 语文     56.0
    5   2005002 数学     69.0
    6   2005002 英语     89.0

    执行

    select sid,语文=isnull(sum(case course when '语文' then result end),0),
       数学=isnull(sum(case course when '数学' then result end),0),
       英语=isnull(sum(case course when '英语' then result end),0)
       from result
       group by sid
       order by sid


    得出结果

    sid           语文 数学 英语

    2005001 80.0 90.0 80.0
    2005002 56.0 69.0 89.0


    2)较为复杂的行转列

    表1:course

    id name

    1 语文
    2 数学
    3 英语


    表2:result

    id sid          course result

    1 2005001 语文      80.0
    2 2005001 数学      90.0
    3 2005001 英语      80.0
    4 2005002 语文      56.0
    5 2005002 数学      69.0
    6 2005002 英语      89.0


    declare @sql varchar(8000)
    set @sql='select sid'
    select @sql=@sql+','+course.name+'=isnull(sum(case course when '''+course.name+''' then result end),0)'
    from course order by id
    set @sql=@sql+' from result group by sid order by sid'
    print @sql
    exec(@sql)


    得出结果

    sid           语文 数学 英语

    2005001 80.0 90.0 80.0
    2005002 56.0 69.0 89.0

    -----------------列转行---------------------------------------------------------------------------------------------------------

    有字符串'1,2,3,4,5,,6,7,8,'这样的不定长字符串,要求将其转成一列N行来存储,也就是列转行,哪种方式最快.

    经过讨论,下列方式最快.

    declare @var varchar(8000)
        ,@sql varchar(8000)
        ,@last varchar(1)
        ,@ctrl int
    set @var='1,2,3,4,5,,6,7,'
    set @ctrl=0
    while @ctrl=0
    begin
    if (select charindex(',,',@var))>0
        select @var=replace(@var,',,',',')
    else
        set @ctrl=1
    end

    set @last=right(@var,1)

    if @last=','
    set @var=left(@var,len(@var)-1)

    set @sql='select '+replace(@var,',',' union all select '


     


    -------------------------------------------------可运行的------------------------------------

    --交叉表语句的实现:
    CREATE TABLE Test
    (
    id int IDENTITY(1,1) NOT NULL,
    name nvarchar(50) NULL,
    subject nvarchar(50) NULL,
    Source numeric(18,0) NULL
    )

    GO

    INSERT INTO [test] ([name],[subject],[Source]) values (N'张三',N'语文',60)
    INSERT INTO [test] ([name],[subject],[Source]) values (N'李四',N'数学',70)
    INSERT INTO [test] ([name],[subject],[Source]) values (N'王五',N'英语',80)
    INSERT INTO [test] ([name],[subject],[Source]) values (N'王五',N'数学',75)
    INSERT INTO [test] ([name],[subject],[Source]) values (N'王五',N'语文',57)
    INSERT INTO [test] ([name],[subject],[Source]) values (N'李四',N'语文',80)
    INSERT INTO [test] ([name],[subject],[Source]) values (N'张三',N'英语',100)

    Go

    SELECT * FROM TEST

    --用于:交叉表的列数是确定的
    select name,sum(case subject when '数学' then source else 0 end) as '数学',
    sum(case subject when '英语' then source else 0 end) as '英语',
    sum(case subject when '语文' then source else 0 end) as '语文'
    from test
    group by name

    --用于:交叉表的列数是不确定的
    declare @sql varchar(8000)
    set @sql = 'select name'
    select @sql = @sql + ',sum(case subject when '''+subject+'''
          then source else 0 end) as '''+subject+''' '
    from (select distinct subject from test) as a
    select @sql = @sql + ' from test group by name'
    exec(@sql)

  • 相关阅读:
    程序猿神吐槽,说出那些苦逼的日子!
    java设计模式演示样例
    DP Leetcode
    标准差(standard deviation)和标准误差(standard error)你能解释清楚吗?
    移动开发 Native APP、Hybrid APP和Web APP介绍
    Oracle cloud control 12c 的启动与关闭
    Ubuntu文件的复制、移动和删除命令
    Android中集成第三方库的方法和问题
    腾讯QQ企业邮箱POP3/SMTP设置
    又发现支付宝和淘宝的设计漏洞
  • 原文地址:https://www.cnblogs.com/hanguoji/p/1661756.html
Copyright © 2011-2022 走看看