sql - 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)
我错了,还是应该工作?
解决方案
我通常通过左连接来执行此操作,该连接查找连接失败时创建的空值:
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中没有匹配数据”的所有识别模式
推荐阅读
- python-3.x - 使用 CSV 文件中的名称列表遍历 API
- automated-tests - 赛普拉斯报告元素尺寸错误
- acumatica - Acumatica。如何根据给定日期创建参数
- laravel - Laravel 中可重用和独立的模块?
- react-native - 以平滑的方式更改 TextInput 的 fontSize
- ansible - Ansible 来自 /etc/ansible/hosts 的五个随机主机
- pandas - groupby pandas dataframe,取最新日期和最早日期的值之间的差异
- nginx - 404 时重定向到另一个站点
- kentico - 带有自定义查询的 Kentico 中继器
- sql-server - 将删除后触发器替换为代替触发器