INTERSECT比子查询更受欢迎吗?

时间:2016-04-01 13:24:30

标签: mysql

我正在处理问题

  

查找所有未出现在“喜欢”表格中的学生(作为喜欢或喜欢的学生)并返回他们的姓名和成绩。按等级排序,然后按每个等级的名称排序。

我建议做以下事情,让所有没有喜欢的人与那些不喜欢任何人的人交往:

SELECT name, grade
  FROM Highschooler h1
LEFT JOIN Likes l1
  ON (l1.ID1 = h1.ID)
WHERE l1.ID1 IS NULL
INTERSECT
SELECT name, grade
  FROM Highschooler h1
LEFT JOIN Likes l1
  ON (l1.ID2 = h1.ID)
WHERE l1.ID2 IS NULL
ORDER BY grade, name

另一种方法是使用子查询(我在网上找到)

select name, grade from Highschooler H1
where H1.ID not in (select ID1 from Likes union select ID2 from Likes) 
order by grade, name;

首选哪种方式?我认为我的方法更具可读性。

2 个答案:

答案 0 :(得分:0)

像阿德里安说的那样,两者都是可以接受的方式, 我认为你的方式更具可读性,因为大写的函数和更好的缩进而不是因为查询本身。

我就是这样做的例子:

SELECT name, grade
FROM Highschooler H1
LEFT JOIN Likes AS L1 ON L1.ID1 = H1.ID OR L1.ID2 = H1.ID
WHERE L1.ID1 IS NULL
ORDER BY grade, name

这种情况称为反连接。阅读更多关于这些的信息

https://explainextended.com/2009/09/18/not-in-vs-not-exists-vs-left-join-is-null-mysql/

这是另一篇不错的博客文章,关于不同类型的联接以及它们附带的一些图表: http://blog.jooq.org/2015/10/06/you-probably-dont-use-sql-intersect-or-except-often-enough/

我们的案例是Left Anti Join

答案 1 :(得分:0)

不,您的查询不太可读。用简单的英语阅读:1。列出所有学生及其喜欢的大型名单。 2.如果没有为学生找到喜欢的记录,请保留学生记录。 3.然后删除所有包含喜欢的记录(因此只保留那些没有喜欢的学生)。 4.-6。对喜欢的表中的其他人做同样的事情。 7.将两个结果集相交。

原始任务仅限于:找到喜欢的表中不存在的学生。

select name, grade
from highschooler
where not exists
(
  select *
  from likes
  where likes.id1 = highschooler.id
     or likes.id2 = highschooler.id
)
order by grade, name;

让您的查询尽可能简单。 SQL的读取或多或少与您用英语说出任务一样。以这种简单的形式制定任务并不总是可行的,但你总是可以尝试: - )

您在交叉查询中使用的反连接模式是克服年轻DBMS中尚未与IN和EXISTS处理良好的弱点的技巧。你应该只在必要时使用技巧,而不是在处理给定的那么简单的任务时使用。