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

    本文使用的方法:

    1、用Case When

    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

    以上为知道学科有“语文、数学、英语”,如果不确定科目呢?

    此时可以用动态SQL查询,请看进阶版

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

    方法三、 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
  • 相关阅读:
    使用ffmpeg将mp4切片成ts slice 并生成m3u8命令,同时让IIS支持支持 m3u8
    C# 自动下移动光标 。winform 发送tab,在WPF中
    C# 获取当前程序路径方法整理
    Jeecg-Boot 2.0.0 版本发布,基于Springboot+Vue 前后端分离快速开发平台
    vue2.0源码-丰富的选项合并策略
    JavaScript 核心原理精讲
    前端性能优化
    Vue Router模式
    css3实现圆角三角形
    CSS动画
  • 原文地址:https://www.cnblogs.com/kylan/p/10844414.html
Copyright © 2011-2022 走看看