zoukankan      html  css  js  c++  java
  • SQL Server行转列、不确定列的行转列

    原文链接:https://www.cnblogs.com/kylan/p/10844414.html

    本文使用的方法:

    1、用Case When,个人推荐使用case when 的方法,比较灵活(原理是:使用group by 达到distinct 的效果,使多行变为1行)

    2、PIVOT函数

    -- 创建模拟数据
    CREATE TABLE #TempSubjectResult(StudentName NVARCHAR(50) NOT NULL,StudentSubject NVARCHAR(50) NOT NULL,StudentGrade DECIMAL(4,1) NOT NULL)
    INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小姚','语文','80')
    INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小姚','数学','70')
    INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小姚','英语','60')
    INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小明','语文','90')
    INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小明','数学','95')
    INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小明','英语','98')
    
    
    SELECT * FROM #TempSubjectResult

    表数据为:

    -----------------------------------------------------------------------------普通版:转置的列确定-----------------------------------------------------------------------

    方法一:Case When

    -- 1 Case When普通版
    SELECT StudentName 学生名,
           MAX(CASE WHEN StudentSubject='语文' THEN StudentGrade END) 语文,
           MAX(CASE WHEN StudentSubject='数学' THEN StudentGrade END) 数学,
           MAX(CASE WHEN StudentSubject='英语' THEN StudentGrade END) 英语
      FROM #TempSubjectResult
     GROUP BY StudentName

    方法二:PIVOT函数

    SELECT * 
      FROM #TempSubjectResult 
      PIVOT(MAX(StudentGrade) FOR StudentSubject IN([语文],[数学],[英语])) T

    -----------------------------------------------------------------------------升级版:转置的列不确定---------------------------------------------------------------------

    方法三、 Case When升级版 动态SQL

    -- Case When升级版 动态SQL
    DECLARE @SqlText NVARCHAR(4000)='SELECT StudentName ''学生名'', ' -- SQL头部分 SELECT
    SELECT @SqlText=@SqlText+' MAX(CASE WHEN StudentSubject='''+StudentSubject+''' THEN StudentGrade END) '''+StudentSubject +''',' FROM (SELECT DISTINCT StudentSubject FROM #TempSubjectResult) T -- 拼接CASE WHEN 
    SELECT @SqlText= LEFT(@SqlText,LEN(@SqlText)-1)+' FROM #TempSubjectResult GROUP BY StudentName' -- 拼接 FROM后面部分
    PRINT @SqlText
    EXEC (@SqlText)

    方法四、PIVOT升级版 动态SQL

    DECLARE @SqlSubject NVARCHAR(4000)
    SELECT @SqlSubject= STUFF((SELECT ','+'['+StudentSubject+']' FROM (SELECT DISTINCT StudentSubject FROM #TempSubjectResult) T  FOR XML PATH('')),1,1,'') -- 获取PIVOT科目
    DECLARE @SqlPIVOT NVARCHAR(4000)='SELECT * FROM #TempSubjectResult PIVOT(MAX(StudentGrade) FOR StudentSubject IN('+@SqlSubject+')) T' -- 拼接PIVOT
    PRINT @SqlPIVOT
    EXEC (@SqlPIVOT)

    以下情况推荐使用动态转换:

    1、需要转置的列不确定,比如转置月的天数,月份的天数有28.29.30.31天,不确定
    2、需要转置的列非常多时候,不方便一个个写

    附:完整代码

    -- 创建模拟数据
    CREATE TABLE #TempSubjectResult
    (
    StudentName NVARCHAR(50) NOT NULL,
    StudentSubject NVARCHAR(50) NOT NULL,
    StudentGrade DECIMAL(4,1) NOT NULL
    )
    INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小姚','语文','80')
    INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小姚','数学','70')
    INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小姚','英语','60')
    INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小明','语文','90')
    INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小明','数学','95')
    INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小明','英语','98')
    
    SELECT * FROM #TempSubjectResult
    
    -- 1 Case When普通版
    SELECT StudentName 学生名,
           MAX(CASE WHEN StudentSubject='语文' THEN StudentGrade END) 语文,
           MAX(CASE WHEN StudentSubject='数学' THEN StudentGrade END) 数学,
           MAX(CASE WHEN StudentSubject='英语' THEN StudentGrade END) 英语
      FROM #TempSubjectResult
     GROUP BY StudentName
    
    -- 2 PIVOT普通版
    SELECT * FROM #TempSubjectResult PIVOT(MAX(StudentGrade) FOR StudentSubject IN([语文],[数学],[英语])) T
    
    -- 3 Case When升级版 动态SQL
    DECLARE @SqlText NVARCHAR(4000)='SELECT StudentName ''学生名'', ' -- SQL头部分 SELECT
    SELECT @SqlText=@SqlText+' MAX(CASE WHEN StudentSubject='''+StudentSubject+''' THEN StudentGrade END) '''+StudentSubject +''',' FROM (SELECT DISTINCT StudentSubject FROM #TempSubjectResult) T -- 拼接CASE WHEN 
    SELECT @SqlText= LEFT(@SqlText,LEN(@SqlText)-1)+' FROM #TempSubjectResult GROUP BY StudentName' -- 拼接 FROM后面部分
    PRINT @SqlText
    EXEC (@SqlText)
    
    -- 4 PIVOT升级版 动态SQL
    DECLARE @SqlSubject NVARCHAR(4000)
    SELECT @SqlSubject= STUFF((SELECT ','+'['+StudentSubject+']' FROM (SELECT DISTINCT StudentSubject FROM #TempSubjectResult) T  FOR XML PATH('')),1,1,'') -- 获取PIVOT科目
    DECLARE @SqlPIVOT NVARCHAR(4000)='SELECT * FROM #TempSubjectResult PIVOT(MAX(StudentGrade) FOR StudentSubject IN('+@SqlSubject+')) T' -- 拼接PIVOT
    PRINT @SqlPIVOT
    EXEC (@SqlPIVOT)
    DROP TABLE #TempSubjectResult

     行转列的弊端是:如果某个值有多行,则只会出现根据聚合函数出现其中的一个值,其它值不体现

    例:

     

  • 相关阅读:
    animate()的使用
    jQuery UI中datepicker()的使用
    newsletter 在不同邮箱中发送的问题
    用户评价 打星等级 效果 jQuery
    SpringBoot整合WebSocket
    SpringBoot之自定义拦截器
    SpringBoot整合MyBatis
    EF实体框架简单原理及基本增删改查用法(上)
    数据库内容导出到Excel
    Asp.Net页面生命周期
  • 原文地址:https://www.cnblogs.com/Bokeyan/p/14447537.html
Copyright © 2011-2022 走看看