我有一个如下所示的 SQL:
SELECT * FROM foo WHERE foo.bar IN (SELECT foobar.bar FROM foobar)
这不好,对吧?嵌套的 SELECT 会导致事情变慢吗?我应该如何查询这样的事情?
IN 子句是完全有效的 SQL,但它并不总是首选方式。我经常发现 MySQL 在它们上的性能很差,即使foo.bar
被索引了。
如果将其更改为联接,则必须小心第二张表是否有多行与第一张表的每一行的联接条件匹配,因为联接会产生多个结果行。如果这是可能的,连接应该是:
SELECT f.*
FROM foo f
INNER JOIN (SELECT DISTINCT bar FROM foobar) fb USING (bar);
最终的答案是您应该使用 EXPLAIN 来查看如何执行不同形式的查询。但是,如果您一开始没有遇到性能问题,请不要担心。
如果你想要所有不存在的行f.bar
,通常是foobar
最NOT IN
简洁的写法。但也可以使用 a 来编写LEFT OUTER JOIN
:
SELECT f.*
FROM foo f
LEFT OUTER JOIN foobar fb USING (bar)
WHERE fb.bar IS NULL
在这种情况下,您不需要子查询,因为您只报告不匹配的行,因此结果中显然不能有多个匹配项。
您也可以将其重写为
Select
*
From
foo f
Where
Exists ( -- If you want the opposite, put Not in front here
Select 'x'
From foobar fb
Where f.bar = fb.bar
);
多年来,不同的 DBMS 以不同形式之一更好地处理查询,即使它们都是等效的。我尝试过的大多数现在都可以为两者生成相同的计划。不过,不是我在 mysql 上尝试过的东西。