现有三个数据表,分别是学生表,课程表,成绩表。它们的结构与样例数据如下:
学生
表:
xno xname
1 小王
2 小黑
课程
表:
kno kname
1 语文
2 数学
成绩表
:
cno ckno cf
1 1 86.5
1 2 98.86
2 1 86.7
2 2 86.9
(
xno int ,
xname varchar ( 20 )
)
go
insert into dbo.学生表
select 1 , ' 小王 '
union all
select 2 , ' 小黑 '
create table 课程表
(
kno int ,
kname varchar ( 20 )
)
go
insert into 课程表
select 1 , ' 语文 '
union all
select 2 , ' 数学 '
create table 成绩表
(
cno int ,
ckno int ,
cf float
)
alter table 成绩表
alter column cf
insert into 成绩表
select 1 , 1 , 86.5
insert into 成绩表
select 1 , 2 , 98.86
union all
select 2 , 1 , 86.7
union all
select 2 , 2 , 86.9
select * from 学生表
select * from 课程表
select * from 成绩表
现要求在一行中输出每个学生的所有课程的成绩单,显示样例格式如下:
姓名 语文 数学
小王 60 70
小黑 80 65
当大家看到这样的题目时会优先考虑到的是怎样的一条SQL语句呢?嵌套Select?对,在将行转换为列时,也许这种方法是最优先考虑到
( SELECT cf FROM 成绩表 INNER JOIN 课程表 ON 成绩表.ckno = 课程表.kno WHERE 成绩表.cno = B.xno AND 课程表.kname = ' 语文 ' ) AS 语文,
( SELECT cf FROM 成绩表 INNER JOIN 课程表 ON 成绩表.ckno = 课程表.kno WHERE 成绩表.cno = B.xno AND 课程表.kname = ' 数学 ' ) AS 数学
FROM 学生表 B
这样我们的目的是达到了,但后来我又想了一下,因为我们要的数据其实都在 成绩表 里,只不过现有的是用行来存放,那我们怎么将它转换为列显示呢?嗯,这也许就要搬出聚合函数加Case条件来处理了!最终的SQL语句如下:
MAX ( CASE kname WHEN ' 语文 ' THEN cf ELSE 0 END ) AS 语文,
MAX ( CASE kname WHEN ' 数学 ' THEN cf ELSE 0 END ) AS 数学
FROM ( SELECT B.xname,C.kname,D.cf FROM 成绩表 D
INNER JOIN 学生表 B ON B.xno = D.cno
INNER JOIN 课程表 C ON C.kno = D.ckno) AS ZH GROUP BY xname
运行后,也是可以得到正确的数据,下面给出测试代码,大家可以直接在SQL查询分析器里运行
方法一:
( SELECT cf FROM 成绩表 INNER JOIN 课程表 ON 成绩表.ckno = 课程表.kno WHERE 成绩表.cno = B.xno AND 课程表.kname = ' 语文 ' ) AS 语文,
( SELECT cf FROM 成绩表 INNER JOIN 课程表 ON 成绩表.ckno = 课程表.kno WHERE 成绩表.cno = B.xno AND 课程表.kname = ' 数学 ' ) AS 数学
FROM 学生表 B
方法二:
MAX ( CASE kname WHEN ' 语文 ' THEN cf ELSE 0 END ) AS 语文,
MAX ( CASE kname WHEN ' 数学 ' THEN cf ELSE 0 END ) AS 数学
FROM ( SELECT B.xname,C.kname,D.cf FROM 成绩表 D
INNER JOIN 学生表 B ON B.xno = D.cno
INNER JOIN 课程表 C ON C.kno = D.ckno) AS ZH GROUP BY xname
DROP
TABLE
学生表
DROP
TABLE
课程表
DROP
TABLE
成绩表