Как вы можете найти строки, где два значения отличаются, и одно из них может быть NULL? Почему NULL! = 1 ложно? - PullRequest
2 голосов
/ 23 апреля 2020

В Postgres Я хочу найти строки, в которых один столбец отличается от другого. К моему удивлению, сравнение 1! = NULL дает NULL, что, я думаю, ложное значение, и оно не включено в результаты.

SELECT * FROM (VALUES
  (0, 0),
  (0, 1),
  (1, 0),
  (1, 1),
  (0, NULL),
  (1, NULL),
  (NULL, 0),
  (NULL, 1),
  (NULL, NULL)
) v (x, y)
WHERE x != y

Результаты:

x   y
0   1
1   0

Здесь онлайн SQL скрипка для демонстрации проблемы: https://www.db-fiddle.com/f/hTbJQJw36k3KrrJfUASpn9/0

Я обнаружил, что при сравнении чего-либо с нулем результат всегда равен нулю, и вот как он должен работать .

Так что я могу быть немного ближе, когда я спрашиваю WHERE x = y IS NOT TRUE:

SELECT *, (x!=y) AS comp, (x=y IS NOT TRUE) AS not_true FROM (VALUES
  (0, 0),
  (0, 1),
  (1, 0),
  (1, 1),
  (0, NULL),
  (1, NULL),
  (NULL, 0),
  (NULL, 1),
  (NULL, NULL)
) v (x, y)
x     y     comp  not_true
0     0     false false
0     1     true  true
1     0     true  true
1     1     false false
0     null  null  true
1     null  null  true
null  0     null  true
null  1     null  true
null  null  null  true

Я бы хотел, чтобы последняя строка была истинной хоть. Я понимаю, что я сравниваю что-нибудь с NULL и поэтому получаю NULL, который не является ИСТИННЫМ, так что да.

Я могу написать дополнительное условие, например WHERE (x = y IS NOT TRUE AND (x IS NOT NULL OR y IS NOT NULL)), но это кажется слишком сложным. Вот обновленная SQL скрипка:

https://www.db-fiddle.com/f/hTbJQJw36k3KrrJfUASpn9/1

Есть ли более простой способ?

1 Ответ

2 голосов
/ 23 апреля 2020

Вы можете использовать оператор безопасного сравнения NULL:

where x is distinct from y

Здесь - это db <> скрипка.

Что касается вашего вопроса «почему» , NULL имеет четко определенную семантику (значение) в SQL. Это означает, что значение равно unknown . Следовательно, почти все сравнения возвращают NULL («неизвестно»). Выражение 1 <> NULL оценивается как NULL, поскольку NULL может быть 1 - или любым другим значением.

Стандарт SQL также реализует функциональные возможности, которые обрабатывают это is distinct from и is not distinct from. Postgres является одной из немногих баз данных, которые на самом деле реализуют этот оператор, но SQL имеет соответствующие операторы сравнения для равенства NULL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...