Student表有三列,分别是姓名、课程、成绩
Name Curricula Mark 张三 语文 70 李四 数学 80 王朝 英语 59 城南 马哲 70 王朝 语文 90 我想得到的效果是,列出各个学科及格的人名: 语文 化学 数学 张三 李四 王朝学科不止3门,可能有八门怎么弄呢?其实这就是典型的维度方向变化.
准备数据:
create table stgrade(Name varchar(10), Curricula varchar(10) , Mark int);
goinsert into stgrade values('张三' , '语文','70' );insert into stgrade values('李四' , '数学','80');insert into stgrade values('王朝' , '英语','59');insert into stgrade values('城南' , '马哲','70' );insert into stgrade values('王朝' , '语文','90' );goselect * from stgrade;
Name Curricula Mark
张三 语文 70李四 数学 80王朝 英语 59城南 马哲 70王朝 语文 90用case when 来实现根据column的值来返回同一行别的column的值,因为我们这里不需要分数,只关心Curricula 和name,所以是在分数赛选过后,进行一个case when操作.
select
case when Curricula='语文' then name end 语文,case when Curricula='数学' then name end 数学,case when Curricula='英语' then name end 英语,case when Curricula='马哲' then name end 马哲from stgrade where mark>59
语文 数学 英语 马哲
张三 NULL NULL NULLNULL 李四 NULL NULLNULL NULL NULL 城南王朝 NULL NULL NULL又上面已经可以看到结果集合已经初具雏形了,要是更让每个column下的NULL消失,然后后面行的值补上来就能达到我们的要求了。
select
case when Curricula='语文' then name end 语文,case when Curricula='数学' then name end 数学,case when Curricula='英语' then name end 英语,case when Curricula='马哲' then name end 马哲,snfrom ( select curricula,name,mark, row_number() over(partition by curricula order by name) sn from stgrade where mark>59) t语文 数学 英语 马哲 sn
NULL NULL NULL 城南 1NULL 李四 NULL NULL 1王朝 NULL NULL NULL 1张三 NULL NULL NULL 2select sn,
max(case when Curricula='语文' then name end) 语文,max(case when Curricula='数学' then name end) 数学,max(case when Curricula='英语' then name end) 英语,max(case when Curricula='马哲' then name end) 马哲from ( select curricula,name,mark, row_number() over(partition by curricula order by name) sn from stgrade where mark>59) tgroup by snsn 语文 数学 英语 马哲
1 王朝 李四 NULL 城南2 张三 NULL NULL NULL