为什么即使我知道有0个结果,此PostgreSQL查询仍会产生0个结果

为什么即使我知道有0个结果,此PostgreSQL查询仍会产生0个结果,sql,postgresql,Sql,Postgresql,我的系统中有两个表:journal和journal\u contribution。两者都有一个字段uuid作为主键,journal_贡献包含字段journal_uuid以将其链接到日志。其他领域并不重要。日记账表有461283条记录,日记账贡献336136条记录 我想确定我有多少期刊没有引用它们的期刊贡献 我的第一个想法是下面的问题 select count(*) from journal where uuid not in (select journal_uuid as uuid from

我的系统中有两个表:journal和journal\u contribution。两者都有一个字段uuid作为主键,journal_贡献包含字段journal_uuid以将其链接到日志。其他领域并不重要。日记账表有461283条记录,日记账贡献336136条记录

我想确定我有多少期刊没有引用它们的期刊贡献

我的第一个想法是下面的问题

select count(*)
from journal 
where uuid not in 
(select journal_uuid as uuid
from journal_contribution)
我知道这不是很好,但我很惊讶,2分钟后我得到了0分。 更重要的是,如果我在没有“not”的情况下运行相同的查询,我会得到结果124121。如果我从期刊总数中减去这个数字,我原本预计原始结果是337162

当我将代码更改为以下更高性能的版本时,我确实得到了正确的结果,但我首先想了解0。谁能给我解释一下吗

select count(*)
from journal 
where not exists
(select 1  
from journal_contribution jc
where jc.journal_uuid = journal.uuid)

这些查询是在运行PostgreSQL 11的pgAdmin 4.21中完成的,显然子查询包含空值

将查询更改为

select count(uuid)
from journal 
where uuid not in 
(select distinct journal_uuid as uuid
from journal_contribution
 where journal_uuid is not null)
给出正确的结果

这会产生结果的原因在中得到了回答


EXISTS运算符显然没有空值问题

问题在于journal\u贡献表中的列journal\u uuid可为空。尝试使用IN运算符时,NULL值始终不返回任何内容。就像编写id=NULL之类的东西一样,它不会返回任何结果。
另一个查询正在工作,因为您正在尝试比较日志表中的uuid值,如果我没有错的话,它是主键且不可为null

我强烈建议您不要在子查询中使用not in。原因很简单:空值不是直观地处理的

正如您所观察到的,如果子查询返回的任何行为空,NOT IN将过滤掉所有行

有一个简单的选择:不存在:


此外,此查询还可以使用journal_contributionjournal_uuid上的索引。我猜有了这样一个索引,这个查询会很快。

您检查过子查询中没有空值吗?子查询中有空值。这有什么变化吗?你是对的:如果我在子查询中添加'isnotnull',它会返回正确的结果。为什么?这回答了你的问题吗?比较的数值是相同的。似乎EXISTS没有空值问题在第一个查询中,子查询将返回一组值,其中一个或多个值将为空,因为journal\u contribution.journal\u uuid可为空,因此查询将类似于“select count*from journal where uuid not in NULL”,…值“``将始终不返回任何内容,因为IN运算符会将每个值与=号进行比较,就像id=NULL不起作用一样。第二个查询是这样工作的:子查询将尝试查找具有相同uuid的所有行,如果是,exists函数将返回true或false。
select count(*)
from journal j
where not exists (select 1
                  from journal_contribution jc
                  where jc.journal_uuid = j.uuid
                 );