如何使用 JOIN 而不是 SELECT NOT IN?
How to use JOIN instead of SELECT NOT IN?
我有 2 个表:
- 客户(customer_id、customer_name)
- 文档(document_id、document_name、customer_id)
例如,我希望找到所有没有租赁合同的客户。
我可以这样做:
SELECT contragent_name
FROM contragents
WHERE contragent_id NOT IN (SELECT contragent_id
FROM documents
WHERE document_name = 'Rent contract');
任何人都可以建议如何在没有第二个的情况下做到这一点 select?
使用左连接和过滤器,其中左 table 键为空(但您仍然需要嵌套查询来获取名为 Rent contract 的文档子集):
SELECT c.contragent_name
FROM contragents AS c
LEFT JOIN (
SELECT contragent_id FROM documents WHERE document_name = 'Rent contract'
) AS d ON c.id = d.contragent_id
WHERE d.id IS NULL;
这有时称为受挫加入。受挫连接与未选择连接的性能比较取决于不同的因素,例如正在使用的数据库系统、记录量,有时查询优化器可能使用的数据库 statistics/trends...
好吧,您可以使用左反连接重新表述您的要求:
SELECT c.contragent_name
FROM contragents c
LEFT JOIN documents d
ON d.contragent_id = c.contragent_id AND
d.document_name = 'Rent contract'
WHERE
d.contragent_id IS NULL;
但是,如果您将上面的解释计划和性能与您的子查询方法进行比较,您可能会发现类似的东西。实际上,您当前的方法可以通过添加以下索引轻松提高性能:
CREATE INDEX idx ON documents (contragent_id, document_name);
此索引应允许快速查找 contragents
table 中的任何记录。
左连接是一种替代方法:
SELECT c.contragent_name
FROM contragents AS c
LEFT JOIN documents d.
ON c.contragent_id = d.contragent_id
AND document_name = 'Rent contract'
WHERE d.contragent_id IS NULL;
但通常情况下 NOT EXISTS 条件是最有效的方法(如果 性能存在差异 - 这在很大程度上取决于所使用的实际 DBMS)。
SELECT c.contragent_name
FROM contragents c
WHERE NOT EXISTS (SELECT *
FROM documents d
WHERE d.document_name = 'Rent contract'
AND d.contragent_id = c.contragent_id);
我有 2 个表:
- 客户(customer_id、customer_name)
- 文档(document_id、document_name、customer_id)
例如,我希望找到所有没有租赁合同的客户。
我可以这样做:
SELECT contragent_name
FROM contragents
WHERE contragent_id NOT IN (SELECT contragent_id
FROM documents
WHERE document_name = 'Rent contract');
任何人都可以建议如何在没有第二个的情况下做到这一点 select?
使用左连接和过滤器,其中左 table 键为空(但您仍然需要嵌套查询来获取名为 Rent contract 的文档子集):
SELECT c.contragent_name
FROM contragents AS c
LEFT JOIN (
SELECT contragent_id FROM documents WHERE document_name = 'Rent contract'
) AS d ON c.id = d.contragent_id
WHERE d.id IS NULL;
这有时称为受挫加入。受挫连接与未选择连接的性能比较取决于不同的因素,例如正在使用的数据库系统、记录量,有时查询优化器可能使用的数据库 statistics/trends...
好吧,您可以使用左反连接重新表述您的要求:
SELECT c.contragent_name
FROM contragents c
LEFT JOIN documents d
ON d.contragent_id = c.contragent_id AND
d.document_name = 'Rent contract'
WHERE
d.contragent_id IS NULL;
但是,如果您将上面的解释计划和性能与您的子查询方法进行比较,您可能会发现类似的东西。实际上,您当前的方法可以通过添加以下索引轻松提高性能:
CREATE INDEX idx ON documents (contragent_id, document_name);
此索引应允许快速查找 contragents
table 中的任何记录。
左连接是一种替代方法:
SELECT c.contragent_name
FROM contragents AS c
LEFT JOIN documents d.
ON c.contragent_id = d.contragent_id
AND document_name = 'Rent contract'
WHERE d.contragent_id IS NULL;
但通常情况下 NOT EXISTS 条件是最有效的方法(如果 性能存在差异 - 这在很大程度上取决于所使用的实际 DBMS)。
SELECT c.contragent_name
FROM contragents c
WHERE NOT EXISTS (SELECT *
FROM documents d
WHERE d.document_name = 'Rent contract'
AND d.contragent_id = c.contragent_id);