博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SQL SERVER行转换列及PIVOT
阅读量:4561 次
发布时间:2019-06-08

本文共 4887 字,大约阅读时间需要 16 分钟。

--*****************SQL 行转列***************************
--
创建实例表
IF 
OBJECT_ID(
'
TB
')
IS 
NOT 
NULL
 
DROP 
TABLE TB
GO
--
构建实例数据
CREATE 
TABLE TB(姓名 
NVARCHAR(
10),课程 
NVARCHAR(
10),分数 
INT)
INSERT 
INTO TB 
VALUES(N
'
张三
',N
'
语文
',
74)
INSERT 
INTO TB 
VALUES(N
'
张三
',N
'
数学
',
83)
INSERT 
INTO TB 
VALUES(N
'
张三
',N
'
物理
',
93)
INSERT 
INTO TB 
VALUES(N
'
李四
',N
'
语文
',
74)
INSERT 
INTO TB 
VALUES(N
'
李四
',N
'
数学
',
84)
INSERT 
INTO TB 
VALUES(N
'
李四
',N
'
物理
',
94)
SELECT 
* 
FROM TB 
WITH(NOLOCK)
GO
--***************行转列***************************
--实现课程列值旋转为列名
    
--
使用SQL SERVER 2000静态SQL
     
SELECT 
         姓名
        ,
MAX(
CASE 课程 
             
WHEN N
'
语文
'  
THEN 分数 
             
ELSE 
0 
         
END
AS N
'
语文
' 
        ,
MAX(
CASE 课程 
             
WHEN N
'
数学
'  
THEN 分数 
             
ELSE 
0 
         
END
AS N
'
数学
' 
        ,
MAX(
CASE 课程 
             
WHEN N
'
物理
'  
THEN 分数 
             
ELSE 
0 
         
END
AS N
'
物理
'  
     
FROM TB 
     
GROUP 
BY 姓名
    --SQL SERVER 2000动态SQL,指课程不止语文、数学、物理这三门课程。
    
--
变量按SQL语言顺序赋值
    
DECLARE 
@SQL1 
NVARCHAR(
MAX)
    
SET 
@SQL1
=N
'
SELECT 姓名
'
    
SELECT 
        
@SQL1
=
@SQL1
+N
'
,MAX(CASE 课程 
            WHEN N
'''
+课程
+N
'''
 THEN 分数 
            ELSE 0 
        END)[
'
+课程
+
'
]
'  
    
FROM
            
SELECT 
                
DISTINCT 课程 
            
FROM TB 
         )A  
    
SET 
@SQL1
=
@SQL1
+N
'
 FROM TB GROUP BY 姓名
'
    
EXEC(
@SQL1)
    
--
使用ISNULL(),变量先确定动态部分
    
DECLARE 
@SQL 
NVARCHAR(
MAX)
    
SELECT 
        
@SQL
=
ISNULL(
@SQL
+
'
,
',
''
+N
'
 MAX(CASE 课程 
                WHEN N
'''
+课程
+ N
'''
 THEN 分数 
                ELSE 0 
            END) [
'
+课程
+N
'
]
'  
    
FROM(
            
SELECT 
                
DISTINCT 课程 
            
FROM TB
         )
AS A      
    
SET 
@SQL
=N
'
SELECT 
                   姓名,
'
+
@SQL
+N
'
 FROM TB GROUP BY 姓名
'
    
EXEC(
@SQL)

    PIVOT--列值转换为列名,即行转列

    PIVOT(聚合函数(列) FOR 列 in (…) )AS P
    完整语法:
    Table_Source
    PIVOT
    (
    聚合函数【
MAX,
SUM,等】(value_column)
    
FOR pivot_column【要成为列标题的值的列】
       
IN(列值 
of pivot_column)
    ) 别命
    --使用SQL SERVER 2005静态SQL
 
SELECT 
     姓名
    ,语文
    ,数学
    ,物理 
 
FROM TB 
 PIVOT
 ( 
      
MAX(分数)
FOR 课程 
IN 
     ( 
          语文 
         ,数学 
         ,物理 
     ) 
 )A  
    --使用SQL Server 2005动态SQL
 
--
1使用STUFF( character_expression , start , length ,character_expression ),start 从索引1开始
    
DECLARE 
@SQL2 
NVARCHAR(
MAX)
    
SET  
@SQL2
=
''  
    
SELECT  
@SQL2
= 
@SQL2
+
'
,
'
+课程 
FROM TB 
GROUP 
BY 课程 
    
PRINT 
@SQL2
    
SET 
@SQL2
=
STUFF
@SQL2,
1,
1,
'')
--
去掉首个','
    
PRINT 
@SQL2
    
SET 
@SQL2
=N
'
SELECT * FROM TB PIVOT (MAX(分数) FOR 课程 IN (
'
+ 
@SQL2
+
'
))A
'
    
EXEC
@SQL2)
    --2使用ISNULL()
    
DECLARE  
@SQL3 
NVARCHAR(
MAX)
    
SELECT  
@SQL3
=
ISNULL
@SQL3
+
'
,
',
'')
+课程 
FROM TB 
GROUP 
BY 课程           
    
SET 
@SQL3
=N
'
SELECT * FROM TB PIVOT (MAX(分数) FOR 课程 IN (
'
+ 
@SQL3
+
'
))A
'
    
EXEC
@SQL3)
/*运行结果:
    姓名       语文        数学        物理
    ---------- ----------- ----------- -----------
    张三       74          83          93
    李四       74          84          94
*/
--行转列结果加上总分、平均分
    
--
SQL SERVER 2000静态SQL
    
BEGIN
        
SELECT 
            姓名 
           ,
MAX(
CASE 课程 
                
WHEN N
'
语文
'  
THEN 分数 
                
ELSE 
0 
            
END) 数学 
           ,
MAX(
CASE 课程 
                
WHEN N
'
数学
'  
THEN 分数 
                
ELSE 
0 
            
END) 物理 
           ,
MAX(
CASE 课程 
                
WHEN N
'
物理
'  
THEN 分数 
                
ELSE 
0 
            
END) 语文 
           ,
SUM(分数) 
AS 总分
           ,
CAST(
AVG(分数
*
1.0
AS 
DECIMAL(
4,
2)) 
AS 平均分
        
FROM TB 
        
GROUP 
BY 姓名
    
END
    
--
SQL SERVER 2000动态SQL
    
BEGIN
        
DECLARE 
@SQL4 
nvarchar(
MAX)
        
SELECT 
            
@SQL4
=
ISNULL(
@SQL4
+
'
,
',
'')
+N
'
 MAX(CASE 课程 WHEN N
'''
+课程
+N
'''
 THEN 分数 ELSE 0 END)
' 
+课程
        
FROM (
SELECT 
                  
DISTINCT  课程
              
FROM TB 
           ) 
AS TT
         
SET 
@SQL4
=N
'
SELECT 
                         姓名
                        ,
'
+
@SQL4
++N
'
,SUM(分数)AS 总分
                        ,CAST(AVG(分数*1.0)AS decimal(4,2)) AS 平均分 
                     FROM TB 
                     GROUP BY 姓名
'
        
PRINT 
@SQL4
        
EXEC(
@sql4)
    
END
    
--
SQL SERVER 2005 静态PIVOT
    
BEGIN
        
SELECT 
            A.
*
           ,B.总分
           ,B.平均分 
        
FROM (
                
SELECT 
                    
* 
                
FROM TB 
                PIVOT
                ( 
                     
MAX(分数) 
FOR 课程 
IN 
                    ( 
                         数学 
                        ,语文 
                        ,物理 
                    ) 
                ) 
AS TT
             ) 
AS A 
        
INNER 
JOIN (
            
SELECT 
                姓名
               ,
SUM(分数) 
AS 总分 
               ,
CAST(
AVG(分数
*
1.0
AS 
decimal(
4,
2)) 
AS 平均分 
            
FROM TB 
            
GROUP 
BY 姓名
         ) 
AS B 
            
ON A.姓名
=B.姓名
    
END
    
--
SQL SERVER 2005 动态PIVOT
    
BEGIN
        
DECLARE 
@SQL5 
NVARCHAR(
MAX)
        
SELECT 
            
@SQL5
=
ISNULL(
@SQL5
+ 
'
,
',
'')
+ 课程 
        
FROM TB  
        
GROUP 
BY 课程
        
SET 
@SQL5
=N
'
SELECT * FROM TB PIVOT (MAX(分数) FOR 课程 IN (
'
+
@SQL5
+
'
)) AS TT
'
        
SET 
@SQL5
=N
'
SELECT A.*,B.总分,B.平均分 FROM (
'
+
@SQL5
+N
'
) AS A 
        INNER JOIN (SELECT 姓名,SUM(分数) AS 总分,CAST(AVG(分数) AS DECIMAL(4,2)) AS 平均分 FROM TB GROUP BY 姓名) AS B 
        ON A.姓名=B.姓名
'
                
PRINT 
@SQL5
        
EXEC SP_EXECUTESQL 
@SQL5
    
END
/*运行结果:
    姓名  语文 数学 物理 总分  平均分
    ----------------- ----------- ----
    李四  74   84   94   252   84.00
    张三  74   83   93   250   83.33
*/

 

--另一个例子
--
Create 样例表
IF 
OBJECT_ID(
'
TEST
'
IS 
NOT 
NULL
BEGIN
    
DROP 
TABLE TEST
END
CREATE 
TABLE TEST
(
     ID 
INT
    ,Name 
VARCHAR(
20)
    ,
[
Quarter
] 
INT
    ,
[
Profile
] 
INT
)
--
构建样例数据
INSERT 
INTO TEST 
VALUES(
1,
'
A
',
1,
1000)
INSERT 
INTO TEST 
VALUES(
1,
'
A
',
2,
2000)
INSERT 
INTO TEST 
VALUES(
1,
'
A
',
3,
4000)
INSERT 
INTO TEST 
VALUES(
1,
'
A
',
4,
5000)
INSERT 
INTO TEST 
VALUES(
1,
'
B
',
1,
3000)
INSERT 
INTO TEST 
VALUES(
1,
'
B
',
2,
3500)
INSERT 
INTO TEST 
VALUES(
1,
'
B
',
3,
4200)
INSERT 
INTO TEST 
VALUES(
1,
'
B
',
4,
5500)
--行转换列:四个季度的利润转换成横向显示
--
SQL SERVER 2000 静态SQL
SELECT 
    ID 
   ,Name 
    ,
SUM(
CASE 
[
Quarter
] 
        
WHEN 
1 
THEN 
[
Profile
]
        
ELSE 
0 
    
END
AS N
'
1季度
' 
    ,
SUM(
CASE 
[
Quarter
] 
            
WHEN 
2 
THEN 
[
Profile
]
            
ELSE 
0 
        
END
AS N
'
2季度
' 
    ,
SUM(
CASE 
[
Quarter
] 
            
WHEN 
3 
THEN 
[
Profile
]
            
ELSE 
0 
        
END
AS N
'
3季度
' 
    ,
SUM(
CASE 
[
Quarter
] 
            
WHEN 
4 
THEN 
[
Profile
]
            
ELSE 
0 
        
END
AS N
'
4季度
' 
FROM TEST 
GROUP 
BY ID,Name
--
SQL SERVER 2005 静态PIVOT
SELECT 
   
*
FROM TEST 
PIVOT
(
     
SUM(
[
Profile
]
FOR 
[
Quarter
] 
IN (
[
1
],
[
2
],
[
3
],
[
4
])
AS TT

转载于:https://www.cnblogs.com/jeriffe/archive/2011/03/24/1993575.html

你可能感兴趣的文章
搬运工程 启动!
查看>>
局部加权回归(LWR) Matlab模板
查看>>
Connect to the DSP on C6A8168/DM8168/DM8148 using CCS
查看>>
hibernate在使用getCurrentSession时提示no session found for current thread
查看>>
【Luogu1471】方差(线段树)
查看>>
DEV中svg图标的使用
查看>>
markdown测试
查看>>
Java-Maven-Runoob:Maven 依赖管理
查看>>
杂项-Log:log4net
查看>>
杂项-Java:EL表达式
查看>>
tarroni music
查看>>
unity 使用RotateAround的使用注意
查看>>
[SDOI2009]HH的项链
查看>>
CodeFirst模式,容易引发数据迁移问题(不建议使用)
查看>>
jquery的colorbox关闭并传递数据到父窗
查看>>
使用Nginx、Keepalived构建文艺负载均衡
查看>>
phpmyadmin 开放远程登录的权限
查看>>
linux安装gcc和gcc-c++
查看>>
qq登陆错误提示
查看>>
bzoj 1192: [HNOI2006]鬼谷子的钱袋 思维 + 二进制
查看>>