当我希望它们产生相同的结果时,我有两个SQL查询产生不同的结果。我试图找到没有相应位置的事件数。所有地点都有活动,但活动也可以链接到非地点记录。
以下查询产生的计数为16244,即正确的值。
SELECT COUNT(DISTINCT e.event_id)
FROM events AS e
WHERE NOT EXISTS
(SELECT * FROM locations AS l WHERE l.event_id = e.event_id)
以下查询产生的计数为0。
SELECT COUNT(DISTINCT e.event_id)
FROM events AS e
WHERE e.event_id NOT IN (SELECT l.event_id FROM locations AS l)
以下SQL对数据集进行了一些摘要
SELECT 'Event Count',
COUNT(DISTINCT event_id)
FROM events
UNION ALL
SELECT 'Locations Count',
COUNT(DISTINCT event_id)
FROM locations
UNION ALL
SELECT 'Event+Location Count',
COUNT(DISTINCT l.event_id)
FROM locations AS l JOIN events AS e ON l.event_Id = e.event_id
并返回以下结果
Event Count 139599 Locations Count 123355 Event+Location Count 123355
任何人都可以解释为什么2个初始查询不会产生相同的数字。
答案 0 :(得分:6)
子查询SELECT l.event_id FROM locations AS l
中有一个NULL,所以NOT IN will always evaluate to unknown and return 0 results
SELECT COUNT(DISTINCT e.event_id)
FROM events AS e
WHERE e.event_id NOT IN (SELECT l.event_id FROM locations AS l)
可以从以下示例中看到此行为的原因。
'x'NOT IN(NULL,'a','b')
≡'x'<> NULL和'x'<> 'a'和'x' <> 'B'
≡未知,真实和真实
≡未知
答案 1 :(得分:5)
NOT IN
表单对NULL的工作方式不同。单个NULL
的存在将导致整个语句失败,从而不返回任何结果。
因此event_id
中locations
至少有NULL
个SELECT
COUNT(DISTINCT e.event_id)
FROM
events AS e
LEFT JOIN locations AS l ON e.event_id = l.event_id
WHERE
l.event_id IS NULL
。
此外,您的查询可能更好地写为联接:
NOT EXISTS
[更新:显然,{{1}}版本更快。]
答案 2 :(得分:-1)
和存在的处理方式非常不同。
Select * from T1 where x in ( select y from T2 )
通常按以下方式处理:
select *
from t1, ( select distinct y from t2 ) t2
where t1.x = t2.y;
对子查询进行评估,区分,索引(或散列或排序),然后加入 原始表 - 通常。
与
相反select * from t1 where exists ( select null from t2 where y = x )
处理更像是:
for x in ( select * from t1 )
loop
if ( exists ( select null from t2 where y = x.x )
then
OUTPUT THE RECORD
end if
end loop
它总是导致T1的完整扫描,而第一个查询可以使用索引 在T1(x)。