SQL行列转置

1,381 阅读2分钟

image.png

case when 实现

1.确定新列字段数据来源

课程

2.把新列字段名、值找出来,理清关系

select 姓名,
	(case 课程 when '语文' then 分数 else 0 end) 语文
from 行列转换m

新字段名:课程的值, 新字段的值:如果课程=新字段名,那么用对应行分数做值,否则填充0。

select 姓名,
	(case 课程 when '语文' then 分数 else 0 end) 语文,
	(case 课程 when '数学' then 分数 else 0 end) 数学,
	(case 课程 when '物理' then 分数 else 0 end) 物理
from 行列转换m

有N个不同的课程就会有N列

image.png

select 姓名 as 姓名 ,
  max(case 课程 when '语文' then 分数 else 0 end) 语文,
  max(case 课程 when '数学' then 分数 else 0 end) 数学,
  max(case 课程 when '物理' then 分数 else 0 end) 物理
from 行列转换m
group by 姓名

3.观察规律,去除多余、聚合留存有效

加上聚合函数max(),group by

行列转换.image

4.新字段列数变量

--SQL SERVER 2000 动态SQL,指课程不止语文、数学、物理这三门课程。(以下同)
declare @sql varchar(8000)
set @sql = 'select 姓名 '
select @sql = @sql + ' , max(case 课程 when ''' + 课程 + ''' then 分数 else 0 end) [' + 课程 + ']'
from (select distinct 课程 from 行列转换m) as a
set @sql = @sql + ' from 行列转换m group by 姓名'
exec(@sql)

image.png

pivot实现

sql2005以上版本

select *
from 行列转换m
pivot
(
    max(分数)
    for 课程 in(语文,物理,数学) 
) as t
select 姓名, sum(语文) 语文, sum(isnull(物理,0)) 物理, sum(数学) 数学 from (
	select *
		from 行列转换m
		pivot(
			max(分数)
			for 课程 in(语文,物理,数学) 
		) as t
) as t2
group by 姓名

image.png

pivot方法新列名变量

--SQL SERVER 2005 动态SQLdeclare @sql varchar(8000)
select @sql = isnull(@sql + ',' , '') + 课程 from 行列转换m group by 课程
exec ('select * from (select * from 行列转换m) a pivot (max(分数) for 课程 in (' + @sql + ')) b')

image.png

FOR XML PATH 多行压缩成一行显示

(SELECT DISTINCT (课程+',') FROM 成绩 FOR XML PATH('')) AS 所有课程;

image.png