带有连接等效功能的选择语句中的PostGreSQL子查询(不合理)错误?

问题描述 投票:0回答:1

我在pgsql 9.5.1中有一些有趣的错误

我有2个表,其中包含相关数据contacts (id, name)jobs (id, contact_id, name)

我不确定此查询的有效性(考虑到后面介绍的奇怪行为)。>>

-- get unassigned contacts 
select * from contacts where id not in (select contact_id from jobs);

[在没有工作的情况下使用联系人id = 20的情况进行测试时,我得到了一些(IMO)奇怪的结果(在选择查询和联接等效项之间,结果存在显着差异)。

首先,我需要断言一些先决条件(步骤A)。接下来,我显示带有join的结果(步骤B)。最后,我使用子查询显示结果(步骤D)。(步骤C是D的补充请求,仅在此处突出显示我发现的奇怪内容。)

A-0。检查两个表中是否都有数据:OK
select count(distinct id) from contacts;
--> returns 10100
select count(distinct id) from jobs;
--> returns 12000
select count(distinct id) from contacts where id in (select contact_id from jobs);
--> returns 10000

A-1。在表联系人中获取id = 20的名称:确定
select name from contacts where id=20;
--> returns "NAME"

A-3。检查联系人ID = 20是否不在表作业中:确定
select id from jobs where contact_id=20;
--> returns nothing (0 row)

B。获取具有连接的联系人ID = 20的名称和(空)作业ID:OK
select c.id, c.name, j.id
from contacts c
left join jobs j
on j.contact_id=c.id
where c.id=20;
--> returns 20, "NAME", <NULL>

C。仅当在工作中分配联系人ID时,才获取该联系人ID:20 [确定
select name from contacts where id in (select contact_id from jobs) and id=20;
--> returns nothing (0 row); (that's the expected result)

D。仅当未在工作中分配联系人ID = 20时才可使用:KO
select name from contacts where id not in (select contact_id from jobs) and id=20;
--> returns nothing (0 row); (that's not the expected result - "NAME")

有趣的结论

C和D查询得到相同的结果。

从逻辑上讲,这可能意味着在pgsql中:

id NOT IN (..values..)  ==  id IN (..values..)
FALSE == TRUE

“ pgsql专家”可以给我一个很好的解释,还是应该给联邦调查局打电话?

我在pgsql 9.5.1中有一个有趣的错误,我得到2个表,其中包含相关数据联系人(id,姓名)和工作(id,contact_id,姓名)。我不确定此查询的有效性(鉴于好奇...

postgresql
1个回答
2
投票

您看到的是null安全问题。如果not in子查询返回的任何值为null,则将忽略所有其他值。我们说not in不是null安全的。

© www.soinside.com 2019 - 2024. All rights reserved.