Postgres在WHERE id!= int查询中排除NULL

时间:2013-11-14 09:54:03

标签: postgresql null where

昨天我在Postgres尝试从统计信息表中过滤出用户ID时遇到了一个奇怪的问题。例如,当我们user_id != 24时,postgres也会排除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行为吗?

2 个答案:

答案 0 :(得分:14)

你的“解决方法”是通常的做法。一切都表现得像预期的那样。

原因很简单:nulls既不等于也不等于任何东西。当你认为null意味着“未知”时,这是有道理的,并且与未知值的比较的真实性也是未知的。

推论是:

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

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

答案 1 :(得分:1)

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

  

不相等,将null视为普通值

因此只需执行id IS DISTINCT FROM 1即可。

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