题目
有这样一张score表,要查询出课程号为02的成绩大于课程号01的成绩的学生学号。通过观察应该是学号为‘01’,学号‘03’因为是两个成绩相等都是80分所以不符合,而02和04的同学因为没有学01课程所以也不符合。
解法思路
行与行之间的比较可以考虑关联子查询,代码如下:
SELECT A.学号
FROM score A
WHERE A.课程号='02'
AND A.成绩>(SELECT B.成绩
FROM score B
WHERE B.学号=A.学号
AND B.课程号='01')
如果不考虑行与行之间的比较的话,可以考虑join,将行与行的比较转换成列与列的比较,列与列的比较就简单许多,用where子句就行了。
SELECT T2.学号
FROM (SELECT * FROM score A WHERE A.课程号='01') T1
JOIN (SELECT * FROM score B WHERE B.课程号='02') T2
ON T1.学号=T2.学号
WHERE T1.成绩<T2.成绩
其实这里我觉得应该用join会比较好,网上很多答案都是用left join,但是用left join其实也不会出错。虽然会出现类似于如下的空值(下表来源不同,只为说明理由举例),如06号学生并没有学02的课程,当执行06号的where子句时,相当于执行
WHERE T1.成绩<null
但是null是不能用比较谓词的,比如 <、>、<>这些都是无效的,返回值都是UNKNOW,既不是True,也不是False。这就是SQL的三值逻辑。即
True False Unknow,所以不会返回06号的同学学号。关于NULL可以讲解详细点的。
最后也可以考虑EXISTS子句:
SELECT A.学号
FROM score A
WHERE EXISTS(SELECT *
FROM score B
WHERE A.学号=B.学号
AND A.课程号='01'
AND B.课程号='02'
AND A.成绩<B.成绩)
其实和关联子查询思想差不多。