3

我有 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)

提前致谢!!

4

4 回答 4

9

not in您使用的子查询,无论是minus还是其他,通常都是低效的。常见的方法是left join

select name 
from student 
left join student_course on id = st_id
where st_id is NULL

使用join是“正常”和首选的解决方案。

于 2013-06-29T12:46:23.517 回答
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,就像在这种LEFT JOIN ... WHERE ... IS NULL情况下一样。这在具有大量范围表条目的查询中特别有用。
  • (NOT) IN容易出错(NULL),并且在某些实现上可能表现不佳(必须从不相关子查询的结果中删除重复项和 NULL)
于 2013-06-29T14:25:16.167 回答
0

使用“不在”通常很慢。这使您的第二个查询最有效。不过,您可能不需要括号。

于 2013-06-29T12:42:29.480 回答
0

就像评论一样:我建议选择学生 ID(这是唯一的)而不是名称。

作为另一个查询选项,您可能希望加入两个表,按 student_id 分组,count(course_id) 具有 count(course_id) = 0。

另外,我同意索引会更重要。

于 2013-06-29T12:54:16.597 回答