Postgres исключает NULL в WHERE id!= Int query
Вчера я столкнулся с непонятной проблемой в Postgres, пытаясь отфильтровать идентификаторы пользователей из таблицы статистики. Когда мы это сделали, например, user_id != 24
, postgres исключили строки, в которых user_id
есть NULL
.
Я создал следующий тестовый код, который показывает те же результаты.
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?
Ответы
Ответ 1
Ваша "работа вокруг" - это обычный способ сделать это. Все ведет себя как ожидалось.
Причина проста: нули не равны и не равны ни для чего. Это имеет смысл, если вы считаете, что значение null означает "неизвестный", а истина сравнения с неизвестным значением также неизвестна.
Следствие таково:
-
null = null
неверно
-
null = some_value
неверно
-
null != some_value
неверно
Существуют два специальных сравнения IS NULL
и IS NOT NULL
, предназначенные для тестирования, если столбец или нет, null
. Никакие другие сравнения с нулем не могут быть правдой.
Ответ 2
Предикат IS DISTINCT FROM
существует для этой цели. Это описано как:
не равно, рассматривая ноль как обычное значение
Так что просто делать id IS DISTINCT FROM 1
должно работать.
Ссылка: https://www.postgresql.org/docs/11/functions-comparison.html