EXISTS 和 JOIN 之间检查记录是否存在的区别
Difference between EXISTS and JOIN to check existence of records
看下面的例子:
SELECT *
FROM customers
WHERE EXISTS
(SELECT *
FROM order_details
WHERE customers.customer_id = order_details.customer_id)
;
检索相同结果集的两个表之间基于 inner join
的等效查询有哪些区别?
我关心的是 technical/performance 方面,而不是代码的 readability/mantainabilty。
EXISTS 在逻辑上的工作方式如下
for x in (select * from customers)
loop
-- check if x.customer_id exists in order_details table.
---if yes
--output the customer tables row
-- else
--ignore
end if;
end loop;
所以在存在查询中,计划通常会使用嵌套循环(虽然不是硬性规则)
JOIN 查询的逻辑等价物如下
for x in (select * from customers)
loop
--for each row in customer
-- fetch records from order_details which match this condition
select * from order_details where customer_id=x.customerid
end loop;
使用 EXISTS
子句,您 select 存在至少一个 order_details 记录的所有客户。
SELECT *
FROM customers c
WHERE EXISTS (SELECT * FROM order_details od WHERE od.customer_id = c.customer_id);
通过加入,您会再次 select 这些客户。但是,只要它们存在 order_detail,您就会 select 每个。 IE。你会有很多重复。
SELECT c.*
FROM customers c
JOIN order_details od ON c.customer_id = od.customer_id;
您可以使用 DISTINCT
从结果中删除重复项,以便再次获得每个客户一次:
SELECT DISTINCT c.*
FROM customers c
JOIN order_details od ON c.customer_id = od.customer_id;
但为什么生成了所有重复项却不得不再次删除它们?不要这样做。仅在您真正想要合并结果时才加入。
我认为比 EXISTS
子句更具可读性的另一个选项是 IN
子句。这将是我编写查询的方式:
SELECT * FROM customers WHERE customer_id IN (SELECT customer_id FROM order_details);
EXISTS()
被称为"semi-join"。它开始 JOIN
,但在找到第一个匹配项时停止。因此,EXISTS
将比任何等效的 JOIN
.
更快
此外,EXISTS( SELECT * ... WHERE ... )
并不真正关心*
。它将使用任何最佳索引来发现匹配 WHERE
的行是否存在,然后它 returns 1 或 0(意思是 "true" 或 "false")。
当然,如果 LEFT JOIN
将要 return 0 或 1 行,不会更多,则性能差异不大。除了 LEFT JOIN
将 return 来自 table 的值。
看下面的例子:
SELECT *
FROM customers
WHERE EXISTS
(SELECT *
FROM order_details
WHERE customers.customer_id = order_details.customer_id)
;
检索相同结果集的两个表之间基于 inner join
的等效查询有哪些区别?
我关心的是 technical/performance 方面,而不是代码的 readability/mantainabilty。
EXISTS 在逻辑上的工作方式如下
for x in (select * from customers)
loop
-- check if x.customer_id exists in order_details table.
---if yes
--output the customer tables row
-- else
--ignore
end if;
end loop;
所以在存在查询中,计划通常会使用嵌套循环(虽然不是硬性规则)
JOIN 查询的逻辑等价物如下
for x in (select * from customers)
loop
--for each row in customer
-- fetch records from order_details which match this condition
select * from order_details where customer_id=x.customerid
end loop;
使用 EXISTS
子句,您 select 存在至少一个 order_details 记录的所有客户。
SELECT *
FROM customers c
WHERE EXISTS (SELECT * FROM order_details od WHERE od.customer_id = c.customer_id);
通过加入,您会再次 select 这些客户。但是,只要它们存在 order_detail,您就会 select 每个。 IE。你会有很多重复。
SELECT c.*
FROM customers c
JOIN order_details od ON c.customer_id = od.customer_id;
您可以使用 DISTINCT
从结果中删除重复项,以便再次获得每个客户一次:
SELECT DISTINCT c.*
FROM customers c
JOIN order_details od ON c.customer_id = od.customer_id;
但为什么生成了所有重复项却不得不再次删除它们?不要这样做。仅在您真正想要合并结果时才加入。
我认为比 EXISTS
子句更具可读性的另一个选项是 IN
子句。这将是我编写查询的方式:
SELECT * FROM customers WHERE customer_id IN (SELECT customer_id FROM order_details);
EXISTS()
被称为"semi-join"。它开始 JOIN
,但在找到第一个匹配项时停止。因此,EXISTS
将比任何等效的 JOIN
.
此外,EXISTS( SELECT * ... WHERE ... )
并不真正关心*
。它将使用任何最佳索引来发现匹配 WHERE
的行是否存在,然后它 returns 1 或 0(意思是 "true" 或 "false")。
当然,如果 LEFT JOIN
将要 return 0 或 1 行,不会更多,则性能差异不大。除了 LEFT JOIN
将 return 来自 table 的值。