• 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:字符分割
    Java 线程池:newFixedThreadPool
    人类有限的自制力是相当脆弱的
    Arcgis模型构建器案例教程while和for实现通用的循环迭代功能
    通用化全功能、可视化搭建式、扁平化流线型、无代码零基础、探索式启发法、案例式现场化的ArcGIS模型构建器教程教材培训
    Arcgis模型构建器案例教程——while循环递归查找所有相邻的要素
    广西崇左市各地建成区排名最小是大新县
    Arcgis地理处理工具案例教程——批量修改坐标系
    Arcgis模型构建器可视化编程案例教程添加要素个数到文件名,要素类是否为空,删除空白要素类数据文件,删除工作空间里的空白数据文件
    Arcgis地理处理工具案例教程——多边形图层的最小覆盖范围边界
  • 原文地址:https://www.cnblogs.com/hanguoji/p/1661756.html
Copyright © 2020-2023  润新知