我们假设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相关的问题,但不完全是我正在寻找的问题。那么,关于如何使用连接编写它的任何想法?
答案 0 :(得分:5)
一般答案是:
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
我认为您可以将此应用于您的情况。
答案 1 :(得分:2)
select distinct d1.F_ID
from DOC d1
left outer join (
select F_ID
from DOC
where date >= '2000-01-05'
) d2 on d1.F_ID = d2.F_ID
where d1.date < '2000-01-05'
and d2.F_ID is null
答案 2 :(得分:1)
如果我理解你的问题,你想要找到代表仅包含'2000-01-05'之前的文件的文件夹的F_ID,那么只需
SELECT F_ID
FROM DOC
GROUP BY F_ID
HAVING MAX(DATE) < '2000-01-05'
答案 3 :(得分:0)
样本表和插入语句
CREATE TABLE `tleft` (
`id` int(2) NOT NULL,
`name` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `tright` (
`id` int(2) NOT NULL,
`t_left_id` int(2) DEFAULT NULL,
`description` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
INSERT INTO `tleft` (`id`, `name`)
VALUES
(1, 'henry'),
(2, 'steve'),
(3, 'jeff'),
(4, 'richards'),
(5, 'elon');
INSERT INTO `tright` (`id`, `t_left_id`, `description`)
VALUES
(1, 1, 'sample'),
(2, 2, 'sample');
左加入: SELECT l.id,l.name FROM tleft l LEFT JOIN tright r ON l.id = r.t_left_id ;
返回ID:1、2、3、4、5
右加入: SELECT l.id,l.name FROM tleft l RIGHT JOIN tright r ON l.id = r.t_left_id ;
返回ID:1,2
子查询不正确: select id from tleft where id not in ( select t_left_id from tright);
返回ID:3、4、5
对上述子查询的等效联接:
SELECT l.id,l.name FROM tleft l LEFT JOIN tright r ON l.id = r.t_left_id WHERE r.t_left_id IS NULL;
AND
子句将在JOIN期间应用,WHERE
子句将在JOIN之后应用。
示例: SELECT l.id,l.name FROM tleft l LEFT JOIN tright r ON l.id = r.t_left_id AND r.description ='hello' WHERE r.t_left_id IS NULL ;
希望这会有所帮助