in (…) )AS P
注意:PIVOT、UNPIVOT是SQL Server 2005 的语法,使用需修改数据库兼容级别(在数据库属性->选项->兼容级别改为 90 )
SQL2008 中可以直接使用
完整语法:
table_source
PIVOT(
聚合函数(value_column)
FOR pivot_column
IN( <column_list> )
)
View Code
UNPIVOT 用于将列明转为列值(即列转行),在SQL Server 2000可以用UNION来实现
完整语法:
table_source
UNPIVOT(
value_column
FOR pivot_column
IN( <column_list> )
)
典型实例
一、行转列
1 、建立表格
IF OBJECT_ID( ‘ tb ‘ ) IS NOT NULL DROP TABLE tb
go
CREATE TABLE tb(姓名 VARCHAR( 10 ),课程 VARCHAR( 10 ),分数 INT)
insert into tb VALUES ( ‘ 张三 ‘ , ‘ 语文 ‘ , 74 )
insert into tb VALUES ( ‘ 张三 ‘ , ‘ 数学 ‘ , 83 )
insert into tb VALUES ( ‘ 张三 ‘ , ‘ 物理 ‘ , 93 )
insert into tb VALUES ( ‘ 李四 ‘ , ‘ 语文 ‘ , 74 )
insert into tb VALUES ( ‘ 李四 ‘ , ‘ 数学 ‘ , 84 )
insert into tb VALUES ( ‘ 李四 ‘ , ‘ 物理 ‘ , 94 )
go
SELECT * FROM tb
go
姓名 课程 分数
---------- ---------- -----------
张三 语文 74
张三 数学 83
张三 物理 93
李四 语文 74
李四 数学 84
李四 物理 94
2 、使用SQL Server 2000静态SQL
SELECT 姓名,
max(CASE 课程 WHEN ‘ 语文 ‘ THEN 分数 ELSE 0 END) 语文,
max(CASE 课程 WHEN ‘ 数学 ‘ THEN 分数 ELSE 0 END) 数学,
max(CASE 课程 WHEN ‘ 物理 ‘ THEN 分数 ELSE 0 END) 物理
FROM tb
GROUP BY 姓名
3 、使用SQL Server 2000动态SQL
-- SQL SERVER 2000动态SQL,指课程不止语文、数学、物理这三门课程。(以下同)
-- 变量按sql语言顺序赋值
declare@sqlvarchar( 500 )
set @sql= ‘ select姓名 ‘
select @sql=@sql+ ‘ ,max(case课程when ‘‘‘ +课程+ ‘‘‘ then分数else 0 end)[ ‘ +课程+ ‘ ] ‘
from (selectdistinct课程fromtb)a-- 同from tb group by课程,默认按课程名排序
set @sql=@sql+ ‘ from tb group by姓名 ‘
exec(@sql)
-- 使用isnull(),变量先确定动态部分
declare@sqlvarchar( 8000 )
select @sql=isnull(@sql+ ‘ , ‘ , ‘‘ )+ ‘ max(case课程when ‘‘‘ +课程+ ‘‘‘ then分数else 0 end) [ ‘ +课程+ ‘ ] ‘
from (selectdistinct课程fromtb)asa
set @sql= ‘ select姓名, ‘ +@sql+ ‘ from tb group by姓名 ‘
exec(@sql)
4 、使用SQL Server 2005静态SQL
SELECT * FROM tb pivot( MAX(分数) FOR 课程 IN (语文,数学,物理))a
姓名 语文 数学 物理
---------- ----------- ----------- -----------
李四 74 84 94
张三 74 83 93
5 、使用SQL Server 2005动态SQL
-- 使用stuff()
DECLARE @sql VARCHAR( 8000 )
SET @sql = ‘‘ -- 初始化变量 @sql
SELECT @sql = @sql+ ‘ , ‘ + 课程 FROM tb GROUP BY 课程 -- 变量多值赋值
SET @sql = STUFF(@sql, 1 , 1 , ‘‘ )--去掉首个 ‘ , ‘
SET @sql = ‘ select * from tb pivot (max(分数) for 课程 in ( ‘ +@sql+ ‘ ))a ‘
PRINT @sql
exec(@sql)
-- 或使用isnull()
DECLARE @sql VARCHAR( 8000 )
-- 获得课程集合
SELECT @sql = ISNULL(@sql+ ‘ , ‘ , ‘‘ )+ 课程 FROM tb
GROUP BY 课程
SET @sql = ‘ select * from tb pivot (max(分数) for 课程 in ( ‘ +@sql+ ‘ ))a ‘
exec(@sql)
二、行转列结果加上总分、平均分
1 、使用SQL Server 2000静态SQL
-- SQL SERVER 2000静态SQL
select姓名,
max(case课程when ‘ 语文 ‘ then分数else0end)语文,
max(case课程when ‘ 数学 ‘ then分数else0end)数学,
max(case课程when ‘ 物理 ‘ then分数else0end)物理,
sum(分数)总分,
cast(avg(分数 * 1.0 )asdecimal( 18 , 2 ))平均分
fromtb
groupby姓名
姓名 语文 数学 物理 总分 平均分
---------- ----------- ----------- ----------- -----------
李四 74 84 94 252 84.00
张三 74 83 93 250 83.33
2 、使用SQL Server 2000动态SQL
-- SQL SERVER 2000动态SQL
declare@sqlvarchar( 500 )
set @sql= ‘ select姓名 ‘
select @sql=@sql+ ‘ ,max(case课程when ‘‘‘ +课程+ ‘‘‘ then分数else 0 end)[ ‘ +课程+ ‘ ] ‘
from (selectdistinct课程fromtb)a
set @sql=@sql+ ‘ ,sum(分数)总分,cast(avg(分数*1.0) as decimal(18,2)) 平均分from tb group by姓名 ‘
exec(@sql)
3 、使用SQL Server 2005静态SQL
SELECT m. * ,
n.总分 ,
n.平均分
FROM ( SELECT *
FROM tb PIVOT( MAX(分数) FOR 课程 IN ( 语文, 数学, 物理 ) ) a
) m ,
( SELECT 姓名 ,
SUM(分数) 总分 ,
CAST(AVG(分数 * 1.0 ) AS DECIMAL( 18 , 2 )) 平均分
FROM tb
GROUP BY 姓名
) n
WHERE m.姓名 = n.姓名
4 、使用SQL Server 2005动态SQL
-- 使用stuff()
DECLARE @sql VARCHAR( 8000 )
SET @sql = ‘‘
-- 初始化变量@sql
SELECT @sql = @sql + ‘ , ‘ + 课程
FROM tb
GROUP BY 课程
-- 变量多值赋值
--同select @sql = @sql + ‘ , ‘ +课程 from ( select distinct 课程 from tb)a
SET @sql = STUFF(@sql, 1 , 1 , ‘‘ )
--去掉首个 ‘ , ‘
SET @sql = ‘ select m.* , n.总分,n.平均分 from
( select * from ( select * from tb) a pivot (max(分数) for 课程 in ( ‘ + @sql
+ ‘ )) b) m ,
( select 姓名,sum(分数)总分, cast(avg(分数* 1.0 ) as decimal ( 18 , 2 )) 平均分 from tb group by 姓名) n
where m.姓名= n.姓名 ‘
EXEC(@sql)
-- 或使用isnull()
DECLARE @sql VARCHAR( 8000 )
SELECT @sql = ISNULL(@sql + ‘ , ‘ , ‘‘ ) + 课程
FROM tb
GROUP BY 课程
SET @sql = ‘ select m.* , n.总分,n.平均分 from
( select * from ( select * from tb) a pivot (max(分数) for 课程 in ( ‘ + @sql
+ ‘ )) b) m ,
( select 姓名,sum(分数)总分, cast(avg(分数* 1.0 ) as decimal ( 18 , 2 )) 平均分 from tb group by 姓名) n
where m.姓名= n.姓名 ‘
EXEC(@sql)
二、列转行
1 、建立表格
IF OBJECT_ID( ‘ tb ‘ ) IS NOT NULL DROP TABLE tb
go
CREATE TABLE tb(姓名 VARCHAR( 10 ),语文 INT,数学 INT,物理 INT)
INSERT INTO tb VALUES( ‘ 张三 ‘ , 74 , 83 , 93 )
INSERT INTO tb VALUES( ‘ 李四 ‘ , 74 , 84 , 94 )
go
SELECT * FROM tb
姓名 语文 数学 物理
---------- ----------- ----------- -----------
张三 74 83 93
李四 74 84 94
2 、使用SQL Server 2000静态SQL
-- SQL SERVER 2000静态SQL。
select * from
(
select姓名,课程 = ‘ 语文 ‘ ,分数= 语文fromtb
unionall
select姓名,课程 = ‘ 数学 ‘ ,分数= 数学fromtb
unionall
select姓名,课程 = ‘ 物理 ‘ ,分数= 物理fromtb
) t
orderby姓名,case课程when ‘ 语文 ‘ then1when ‘ 数学 ‘ then2when ‘ 物理 ‘ then3end
姓名 课程 分数
---------- ---- -----------
李四 语文 74
李四 数学 84
李四 物理 94
张三 语文 74
张三 数学 83
张三 物理 93
2 、使用SQL Server 2000动态SQL
-- SQL SERVER 2000动态SQL。
-- 调用系统表动态生态。
declare@sqlvarchar( 8000 )
select @sql=isnull(@sql+ ‘ union all ‘ , ‘‘ )+ ‘ select姓名, [课程]= ‘
+quotename(Name, ‘‘‘‘ )+ ‘ , [分数] = ‘ +quotename(Name)+ ‘ from tb ‘
fromsyscolumns
whereName != ‘ 姓名 ‘ andID=object_id( ‘ tb ‘ )-- 表名tb,不包含列名为姓名的其他列
orderbycolid
exec(@sql + ‘ order by姓名 ‘ )
go
3 、使用SQL Server 2005静态SQL
-- SQL SERVER 2005动态SQL
SELECT 姓名 ,
课程 ,
分数
FROM tb UNPIVOT ( 分数 FOR 课程 IN ( [语文], [数学], [物理] ) ) t
4 、使用SQL Server 2005动态SQL
-- SQL SERVER 2005动态SQL
DECLARE @sql NVARCHAR( 4000 )
SELECT @sql = ISNULL(@sql + ‘ , ‘ , ‘‘ ) + QUOTENAME(name)
FROM syscolumns
WHERE id = OBJECT_ID( ‘ tb ‘ )
AND name NOT IN ( ‘ 姓名 ‘ )
ORDER BY colid
SET @sql = ‘ select 姓名,[课程],[分数] from tb unpivot ([分数] for [课程] in( ‘ + @sql
+ ‘ ))b ‘
EXEC(@sql)
SQL 行转列查询汇总
标签:
查看更多关于SQL 行转列查询汇总的详细内容...