查出选修了数据库和数学这两门课程的学生姓名和院系
数据库表,字段信息如下
课程表course:
select * from course ;
cno cname
1001 数学
1002 数据库
1003 语文
学生表student:
select * from student ;
sno sname sex age sdept
20121011 张三 男 18 计算机
20131011 李四 男 17 计算机
20131012 王五 女 16 信息
20131013 赵六 女 19 信息
选课表sc:
select * from sc;
sno cno grade
20131011 1001 100
20131012 1001 70
20131011 1002 98
sql:
SELECT
sname, sdept
from Student
WHERE sno IN (
SELECT sno FROM sc WHERE cno IN (
SELECT cno FROM course WHERE cname = '数学'
AND sno IN (
SELECT sno FROM sc WHERE cno IN (
SELECT cno FROM course
WHERE cname = '数据库' ))));
运行结果为:
sname sdept
李四 计算机
期望的结果是运行失败,因为针对第三层子查询来说,提示语法错误:
SELECT cno FROM course WHERE cname = '数学' AND sno IN (
SELECT sno FROM sc WHERE cno IN (
SELECT cno FROM course WHERE cname = '数据库' ))
[Err] 1054 - Unknown column 'sno' in 'IN/ALL/ANY subquery'
疑问:为什么在子查询失败的情况下,整体查询能正常执行???
估计是你这个版本的mysql有这个容错机制,因为你前面几句查询都是对的,所以他直接忽略后面的错误
个人认为是IN的语法引起的,建议用EXISTS代替,IN语法在查询数据集中如果有空记录会造成查询不正确,可能在整体查询上会作为空来执行,具体可以百度一下IN的问题
子查询报错是因为没有找到sno得那个字段,你sno在学生跟选课表里才有,你单独拎第三段出来去查sno肯定查不到给你报错啊
放在子查询里面查的话他这个sno对的就是上一句sql得sno字段,好像是这样。记得不太清,有错得话望纠正
换成inner join看下,不要搞那么多嵌套in。比如
SELECT sname, sdept
from Student t7
inner join (SELECT sno FROM sc) t6
on t6.sno = t7.sno
inner join (SELECT cno, sno FROM course WHERE cname = '数学') t5
on t5.cno = t6.cno
inner join (SELECT sno FROM sc) t1
on t1.sno = t5.sno
inner join (SELECT cno FROM course WHERE cname = '数据库') t2
on t2.cno = t1.cno;
这是MySQL的优化机制,虽然你写错了in查询,但是优化之后的sql语句,自动帮你把那个不存在的字段放在正确的位置上了。你可以先:
explain [你的sql语句];
show warnings;
查看优化之后的语句