LEFT JOIN ...返回的行数少于 LEFT JOIN ON + AND

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

看来我完全无法理解这些查询结果(PostgreSQL DB):

a) 仅在加入行后才过滤行:

SELECT COUNT(*)
FROM apidata.info x
LEFT JOIN compdata.info a
    ON x.info = a.identifier
WHERE
    a.permit_id IS NULL
    AND a.identifier IS NULL;
count
--------
109242
(1 row)

b) 仅在加入行之前过滤行:

SELECT COUNT(*)
FROM apidata.info x
LEFT JOIN compdata.info a
    ON x.info = a.identifier
    AND a.permit_id IS NULL
WHERE a.identifier IS NULL;
count
--------
111981
(1 row)

c) 行在加入之前和之后都经过过滤:

SELECT COUNT(*)
FROM apidata.info x
LEFT JOIN compdata.info a
    ON x.info = a.identifier
    AND a.permit_id IS NULL
WHERE
    a.permit_id IS NULL
    AND a.identifier IS NULL;
count
--------
111981
(1 row)

我不明白查询 bc 如何可能返回比查询 a 更高的计数。特别是我希望查询 c 返回的计数不高于查询 a,但它返回与查询 b 完全相同的计数。 这是源表中包含数百万行的一些真实数据(我已经概括了表和字段名称),但似乎我无法想象任何更简单的集合会产生类似的结果。

我在这里缺少什么?谁能提供一个更简单的例子吗?

sql postgresql where-clause left-join
1个回答
0
投票
x.info = a.identifier

,然后

a.identifier IS NULL

=

运算符不适用于空值。因此,标识符为空的每一行都不会被连接。因此,where 条件 where

a.identifier IS NULL
是无用的,因为它始终为空。仅具有主表 x 的数据。
问题就在这里。

查询 a 被更积极地过滤,因为

首先加入所有标识符不为空的 compdata 行(实际上与 apidata 中的某些内容匹配)
  • 然后通过检查
  • a.identifier IS NULL
  • ,从结果中删除具有此类匹配的所有行。
    
    
  • 对于 b 和 c,您可以不那么积极地过滤:

首先,仅加入具有匹配标识符
  • 匹配的 Permit_id 的行 然后过滤掉具有匹配连接的所有行。
© www.soinside.com 2019 - 2024. All rights reserved.