首页 > 解决方案 > T-SQL“不在(选择”不工作(如预期)

问题描述

我有一个普通的一对多关系:

customer.id = order.customerid

我想查找没有关联订单的客户。

我试过:

-- one record
select * from customers where id = 123

-- no records
select * from orders where customerid = 123

-- NO RECORDS
select * 
from customers 
where id not in (select customerid from orders)

-- many records, as expected.
select * 
from customers 
where not exist (select customerid from orders 
                 where customers.customerid = customer.id)

我错了,还是应该工作?

标签: sqlsql-serversql-server-2012

解决方案


我通常通过左连接来执行此操作,该连接查找连接失败时创建的空值:

SELECT c.* 
FROM
  customers c
  LEFT JOIN orders o
  ON c.id = o.customerid
WHERE
  o.customerid IS NULL

左连接将客户表视为“实体”并将订单连接到它,其中存在具有给定客户 ID 的订单,并在没有任何匹配订单的地方放置空值,因此关系的订单端在数据。然后说我们只想查看漏洞(通过 where 子句),我们得到一个“没有订单的客户”列表

根据评论,我一直遵守规则“不要将 IN 用于比您准备手动编写的列表更长的时间”,但越来越多的优化器正在重写 IN、EXISTS 和 LEFT JOIN WHERE NULL 查询,使其功能与它们相同'都是“A中的数据在B中没有匹配数据”的所有识别模式


推荐阅读