SQL中EXISTS用作关联查询时的工作原理解惑
关于EXISTS子查询的工作原理解析
你对EXISTS的核心误解在于:它不是判断整个子查询是否有结果,而是对外部查询的每一行,单独执行关联子查询,判断当前行是否能在子查询中找到匹配记录。
针对你给出的查询:
SELECT * FROM suppliers WHERE EXISTS (select * from orders where suppliers.supplier_id = orders.supplier_id);
它的执行逻辑是逐行处理的:
- 从
suppliers表中取出每一条供应商记录 - 针对当前这条供应商的
supplier_id,执行子查询:在orders表中查找是否存在supplier_id与之相等的订单记录 - 如果子查询能找到至少一条匹配的订单,
EXISTS就返回true,这条供应商记录会被保留到最终结果里;如果找不到任何匹配,EXISTS返回false,这条供应商记录会被过滤掉
举个具体例子:
假设suppliers表有3条数据:
| supplier_id | supplier_name |
|---|---|
| 1 | 供应商A |
| 2 | 供应商B |
| 3 | 供应商C |
orders表有2条数据:
| order_id | supplier_id |
|---|---|
| 101 | 1 |
| 102 | 3 |
那么你的查询结果只会包含供应商A和供应商C,因为供应商B没有对应的订单,子查询对它返回空,EXISTS判断为false,所以被过滤。
而你之前误以为的SELECT * FROM suppliers,只有当子查询是无关联的独立查询时才会发生,比如:
SELECT * FROM suppliers WHERE EXISTS (select * from orders);
这种情况下,子查询不依赖外部表的字段,只要orders表不为空,EXISTS就会对所有供应商行返回true,最终返回所有供应商记录。
回到你的原查询,它的效果和内连接去重是一致的:
SELECT DISTINCT s.* FROM suppliers s JOIN orders o ON s.supplier_id = o.supplier_id;
但EXISTS通常效率更高,因为它找到第一条匹配的订单记录后就会停止子查询的执行,不需要返回所有匹配的订单行。
内容的提问来源于stack exchange,提问作者sacacorchos
相关产品推荐
相关产品推荐

