左联接-使用where(null <>'p')时的行为

时间:2019-05-24 19:24:30

标签: sql postgresql left-join

在此选择中,显示4条记录,其中3个空值表示不相关,而一个空值表示相关。

enter image description here

结果:

enter image description here

当我在WHERE pc.contype <> 'p'中添加约束时,仅所有记录,而不仅仅是'p'。

enter image description here

结果:

enter image description here

我无法理解发生了什么,这是我放手的规则吗?

5 个答案:

答案 0 :(得分:1)

所以这里发生的是pg_indexes有4行与您的WHERE条件匹配。当您左联接时,即使没有联接,您也会保留所有行。在您的情况下,只有一行加入pg_constraint。

当LEFT JOIN连接行失败时,它将用NULL填充所有可能的列。这意味着在您的情况下,未连接pg_constraint的3行现在对于pg_constraint指定的所有列都为NULL。

最后,谈到____ <>'p'的比较时,您缺少SQL处理NULL值的规则。 NULL被视为缺少值,而不是您可以比较的值。任何使用标量比较的尝试都将失败。

您可以通过更改为WHERE (pc.contype IS NULL OR pc.contype <> 'p')

来更正此问题

答案 1 :(得分:1)

NULL不等于(或不等于)任何东西,包括NULL本身。忽略您使用的是LEFT JOIN并假设contype可为空:条件WHERE contype <> 'p'不会仅因为NULL <> 'p'是未知的(不是真的)而与NULL不匹配!

您将编写以下内容以获取右表中不匹配的行:

WHERE contype <> 'p' OR contype IS NULL

答案 2 :(得分:1)

您要寻找的是NULL安全比较。 Postgres为此支持ANSI / ISO标准功能,所以我建议:

WHERE contype IS DISTINCT FROM 'p'

这在documentation中有解释。

答案 3 :(得分:0)

您使用的是left join,因此即使pg_indexes对于相同的键没有任何对应的数据,也会总是返回pg_constraints数据。这就是第一次查询中发生的事情。在第二个查询中,您添加了一个检查以仅返回pg_constraints值不为p的数据,这一次NULL的值也将被检查,并且由于检查失败而不会显示。如果此检查位于join子句中,则它仍将显示NULL值,但它位于where子句中,并过滤整个结果集。左联接是外部联接,它将始终从联接左边的表返回所有数据,即使联接右边的相同值不存在,您也要记住这一点。

答案 4 :(得分:0)

pc.contype <> 'p'子句中的附加条件WHERE 有效地击败了外部联接,并将其转换为内部联接。将该谓词放在ON子句中。

您可能想要类似的东西:

select
  pc.contype
from pg_indexes pi
left join pg_constraint pc on pi.indexname = pc.conname
                          and pc.contype <> 'p'
where pi.tablename = 'mytable'