MySQL WHERE子句中两种子查询写法等价性的疑问
两条SQL查询等价的原理解析
先明确你提到的两个查询的本质区别:第一条是非相关子查询,第二条是相关子查询,但最终效果一致,原因如下:
第一条查询的执行逻辑
SELECT Clientname FROM Clients Where ClientID IN (SELECT ClientID FROM Orders WHERE ItemID=2);
- 第一步:先独立执行子查询
SELECT ClientID FROM Orders WHERE ItemID=2,得到所有购买过ItemID=2的客户ID集合(比如[1,3,5])。 - 第二步:遍历Clients表的每一行,检查该行的ClientID是否在第一步得到的集合里,符合条件就返回对应的Clientname。
第二条查询的执行逻辑
SELECT Clientname FROM Clients WHERE (SELECT ClientID FROM Orders WHERE Orders.ClientID=Clients.ClientID AND ItemID=2);
- 这是相关子查询:子查询里的
Orders.ClientID=Clients.ClientID是把外部Clients表当前行的ClientID传到子查询里,所以它不能单独运行(单独运行时没有Clients.ClientID这个外部值)。 - 执行时,会逐行处理Clients表的每一条记录:
- 取出当前客户的ClientID(比如
ClientID=1)。 - 代入子查询执行:
SELECT ClientID FROM Orders WHERE Orders.ClientID=1 AND ItemID=2。 - 如果子查询返回至少一行结果(不管返回的ClientID具体是什么,只要存在这样的订单),WHERE条件就会被判定为
TRUE,当前客户的名字就会被选中。
- 取出当前客户的ClientID(比如
- 换句话说,这个子查询的作用就是验证「当前客户有没有买过ItemID=2的商品」,只要有,条件成立,就返回客户名。
为什么两者等价?
第一条查询是先把所有符合条件的客户ID捞出来,再匹配;第二条是逐个客户验证是否有符合条件的订单。最终筛选出来的都是「买过ItemID=2的客户」,所以结果完全一致。
另外补充一点:SQL中,WHERE子句里的子查询只要返回非空结果集,就会被判定为真——这就是第二条查询里不需要写IN也能生效的关键。
内容的提问来源于stack exchange,提问作者Hữu Trưởng Nguyễn
相关产品推荐
相关产品推荐

