我有3张桌子。以下是结构:
student
(id int, name varchar(20)
)course
(course_id int, subject varchar(10)
)student_course
(st_id int, course_id int
) - >包含注册课程的学生姓名现在,我想写一个查询,找出没有参加任何课程的学生。我可以想象有多种方法可以获取这些信息。能不能让我知道哪一个是最有效的,也是,为什么。此外,如果还有其他更好的执行方式,请告诉我。
db2 => select distinct name from student inner join student_course on id not in (select st_id from student_course)
db2 => select name from student minus (select name from student inner join student_course on id=st_id)
db2 => select name from student where id not in (select st_id from student_course)
提前致谢!!
答案 0 :(得分:9)
您使用的子查询,无论是not in
,minus
还是其他,通常效率低下。执行此操作的常用方法是left join
:
select name
from student
left join student_course on id = st_id
where st_id is NULL
使用join
是“正常”和优先解决方案。
答案 1 :(得分:1)
使用NOT EXISTS
的规范(甚至可能是概要)成语(恕我直言):
SELECT *
FROM student st
WHERE NOT EXISTS (
SELECT *
FROM student_course
WHERE st.id = nx.st_id
);
优点:
NOT EXISTS(...)
已经很老了,大多数优化工作者都知道如何处理它nx.
相关名称泄露到外部查询中:外部查询中的select *
只会从student
表中生成字段,并且而不是student_course
表中的(null)行,就像在LEFT JOIN ... WHERE ... IS NULL
情况下一样。这在具有大量范围表条目的查询中特别有用。(NOT) IN
容易出错(NULL),并且在某些实现上可能会执行错误(必须从不相关子查询的结果中删除重复项和NULL)答案 2 :(得分:0)
使用“not in”通常很慢。这使您的第二个查询最有效。你可能不需要括号。
答案 3 :(得分:0)
正如评论:我建议选择学生ID(这是唯一的),而不是名称。
作为另一个查询选项,您可能希望加入两个表,按student_id分组,count(course_id)具有count(course_id)= 0.
另外,我同意索引会更重要。