假设 MySQL 中的下表描述了文件夹中包含的文档。
mysql> select * from folder;
+----+----------------+
| ID | PATH |
+----+----------------+
| 1 | matches/1 |
| 2 | matches/2 |
| 3 | shared/3 |
| 4 | no/match/4 |
| 5 | unreferenced/5 |
+----+----------------+
mysql> select * from DOC;
+----+------+------------+
| ID | F_ID | DATE |
+----+------+------------+
| 1 | 1 | 2000-01-01 |
| 2 | 2 | 2000-01-02 |
| 3 | 2 | 2000-01-03 |
| 4 | 3 | 2000-01-04 |
| 5 | 3 | 2000-01-05 |
| 6 | 3 | 2000-01-06 |
| 7 | 4 | 2000-01-07 |
| 8 | 4 | 2000-01-08 |
| 9 | 4 | 2000-01-09 |
| 10 | 4 | 2000-01-10 |
+----+------+------------+
列ID是主键,表DOC的列F_ID是引用表FOLDER主键的非空外键。通过在 where 子句中使用文档的“DATE”,我想找到哪些文件夹只包含选定的文档。对于早于 2000-01-05 的文档,这可以写成:
SELECT DISTINCT d1.F_ID
FROM DOC d1
WHERE d1.DATE < '2000-01-05'
AND d1.F_ID NOT IN (
SELECT d2.F_ID
FROM DOC d2 WHERE NOT (d2.DATE < '2000-01-05')
);
并且它正确返回“1”和“2”。通过阅读 http://dev.mysql.com/doc/refman/5.5/en/rewriting-subqueries.html 如果将子查询替换为连接,则可以提高大表的性能。我已经找到了与 NOT IN 和 JOINS 相关的问题,但并不完全是我想要的。那么,关于如何使用连接编写它有什么想法吗?
最佳答案
一般的答案是:
select t.*
from t
where t.id not in (select id from s)
可以重写为:
select t.*
from t left outer join
(select distinct id from s) s
on t.id = s.id
where s.id is null
我认为您可以将此应用于您的情况。
关于mysql - 如何将 NOT IN 子查询重写为连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10592554/