23

昨天,当我试图从统计表中过滤掉用户 ID 时,我在 Postgres 中遇到了一个奇怪的问题。例如,当我们这样做时user_id != 24,postgres 也排除了 where 的user_idNULL

我创建了以下显示相同结果的测试代码。

CREATE TEMPORARY TABLE test1 (
    id int DEFAULT NULL
);

INSERT INTO test1 (id) VALUES (1), (2), (3), (4), (5), (2), (4), (6), 
    (4), (7), (5), (9), (5), (3), (6), (4), (3), (7), 
    (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL);     

SELECT COUNT(*) FROM test1;

SELECT id, COUNT(*) as count
FROM test1
GROUP BY id;

SELECT id, COUNT(*) as count
FROM test1
WHERE id != 1
GROUP BY id;

SELECT id, COUNT(*) as count
FROM test1
WHERE (id != 1 OR id IS NULL)
GROUP BY id;

第一个查询只计算所有行。第二个计算每个值的数量,包括空值。第三个不包括值 1 以及所有空值。第四个是排除值 1 并仍然包含空值的解决方法。

对于我尝试使用此查询的内容,应始终包含空值。

解决这个问题是唯一的方法吗?这是预期的 Postgres 行为吗?

4

2 回答 2

30

您的“解决方法”是通常的方法。一切都按预期运行。

原因很简单:空值既不等于也不等于任何东西。当您认为 null 表示“未知”时,这是有道理的,并且与未知值进行比较的真实性也是未知的。

推论是:

  • null = null不是真的
  • null = some_value不是真的
  • null != some_value不是真的

这两个特殊的比较IS NULLIS NOT NULL用于处理测试列是否为null. 没有其他与 null 的比较是真的。

于 2013-11-14T09:57:00.913 回答
13

IS DISTINCT FROM谓词为此目的而存在。它被描述为:

不相等,将 null 视为普通值

所以只是做id IS DISTINCT FROM 1应该工作。

参考:https ://www.postgresql.org/docs/11/functions-comparison.html

于 2019-01-17T05:00:34.227 回答