Почему SUM (...) на пустом наборе записей возвращает NULL вместо 0?
Я понимаю, почему null + 1
или (1 + null
) возвращает null
: null
означает "неизвестное значение", а если значение неизвестно, его преемник также неизвестен. То же самое верно для большинства других операций с нулевым значением. [*]
Однако я не понимаю, почему происходит следующее:
SELECT SUM(someNotNullableIntegerField) FROM someTable WHERE 1=0
Этот запрос возвращает null
. Зачем? Здесь нет никаких неизвестных значений! Предложение WHERE возвращает нулевые записи, а сумма пустого набора значений 0
. [**] Обратите внимание, что набор не является неизвестным, он, как известно, пуст.
Я знаю, что я могу обойти это поведение, используя ISNULL
или COALESCE
, но я пытаюсь понять, почему это поведение, которое кажется мне интригующим, было выбрано.
Можно ли понять, почему это имеет смысл?
[*] с некоторыми заметными исключениями, такими как null OR true
, где, очевидно, true
является правильным результатом, поскольку неизвестное значение просто не имеет значения.
[**] точно так же, как произведение пустого набора значений 1
. Математически говоря, если бы я должен был расширять $(Z, +) $до $(Z union {null}, +) $, то очевидный выбор для единицы идентичности все равно был бы 0
, а не null
, так как x + 0 = x
но x + null = null
.
Ответы
Ответ 1
ANSI-SQL-Standard определяет результат SUM пустого набора как NULL. Почему они это сделали, я не могу сказать, но по крайней мере поведение должно быть согласованным во всех механизмах баз данных.
Ссылка: http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt на странице 126:
b) Если указаны AVG, MAX, MIN или SUM, то
Case:
i) If TXA is empty, then the result is the null value.
TXA - это оперативный набор результатов из выбранного столбца.
Ответ 2
Когда вы имеете в виду пустую таблицу, вы имеете в виду таблицу с значениями NULL
, поэтому мы получим NULL
как результат для агрегатных функций. Вы можете рассматривать это как по дизайну для SQL Server.
Пример 1
CREATE TABLE testSUMNulls
(
ID TINYINT
)
GO
INSERT INTO testSUMNulls (ID) VALUES (NULL),(NULL),(NULL),(NULL)
SELECT SUM(ID) FROM testSUMNulls
Пример 2
CREATE TABLE testSumEmptyTable
(
ID TINYINT
)
GO
SELECT SUM(ID) Sums FROM testSumEmptyTable
В обоих примерах вы будете NULL
как вывод..