2

假设 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 子句中使用文档的“日期”,我想查找哪些文件夹仅包含选定的文档。对于早于 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 相关的问题,但并不是我想要的。那么,关于如何用 joins 编写它的任何想法?

4

4 回答 4

9

一般的答案是:

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

我认为您可以将此应用于您的情况。

于 2012-05-15T00:03:25.583 回答
3
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
于 2012-05-15T00:02:47.787 回答
1

如果我正确理解您的问题,您想找到代表仅包含“2000-01-05”之前的文档的文件夹的 F_ID,那么只需

SELECT F_ID 
FROM DOC 
GROUP BY F_ID 
HAVING MAX(DATE) < '2000-01-05'
于 2012-05-15T00:22:27.967 回答
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 ;

返回编号: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 ;

希望这可以帮助

于 2018-10-30T14:26:06.350 回答