Почему 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 как вывод..