агрегат пустого результирующего набора - PullRequest
9 голосов
/ 29 июня 2011

Я бы хотел, чтобы агрегаты пустого набора результатов были равны 0. Я попробовал следующее:

SELECT SUM(COALESCE(capacity, 0))
  FROM objects
 WHERE null IS NOT NULL;

Результат:

sum 
-----

(1 row)

Подвопрос: не будет вышеработать в Oracle, используя SUM(NVL(capacity, 0))?

Ответы [ 4 ]

10 голосов
/ 30 июня 2011

С на странице документации о агрегатных функциях:

Следует отметить, что, за исключением count, эти функции возвращают нулевое значение, если нет строквыбран .В частности, sum без строк возвращает ноль, а не ноль, как можно было бы ожидать.Функцию coalesce можно использовать для замены нуля на ноль при необходимости.

Поэтому, если вы хотите гарантировать возвращаемое значение, примените COALESCE к результату SUM, не в его аргументе:

SELECT COALESCE(SUM(capacity), 0) …

Что касается «подзапроса» Oracle, ну, я не смог найти никакого понятия о NULL на официальной странице документа ( для 10.2)., в частности), но два других источника однозначны:

То есть вам не нужноt применять NVL к capacity.(Но, как и в COALESCE в PostgreSQL, вы можете применить его к SUM.)

5 голосов
/ 29 июня 2011

Дело в том, что агрегат всегда возвращает строку, даже если не было агрегированных строк (как в вашем запросе). Вы суммировали выражение без строк. Отсюда и нулевое значение, которое вы получаете.

Попробуйте вместо этого:

select coalesce(sum(capacity),0)
from objects
where false;
1 голос
/ 30 июня 2011

Просто сделайте это:

SELECT COALESCE( SUM(capacity), 0)
FROM objects
WHERE null IS NOT NULL;

Кстати, COALESCE внутри SUM является избыточным, даже если емкость равна NULL, сводка не станет нулевой.

Для остроумия:

create table objects
(
    capacity int null
);

insert into objects(capacity) values (1),(2),(NULL),(3);

select sum(capacity) from objects;

Это вернет значение 6, а не ноль.

И объединение внутри агрегатной функции также является фактором снижения производительности, так как ваша СУБД не может просто перебрать все строки, она должна оценить столбец каждой строки, если его значение равно нулю. Я видел небольшой OCD-запрос, в котором все совокупные запросы имеют слияние внутри, я думаю, что у оригинального разработчика есть симптом Cargo Cult Programming , запрос очень медленный. Я удалил слияние внутри SUM, затем запрос стал быстрым.

0 голосов
/ 17 июля 2012

Хотя этот пост очень старый, но я хотел бы обновить то, что я использую в таких случаях

SELECT NVL(SUM(NVL(capacity, 0)),0)
FROM objects
WHERE false;

Здесь внешний NVL избегает случаев, когда в наборе результатов нет строки. Внутренний NVL используется для нулевых значений столбца, рассмотрим случай (1 + ноль), и это приведет к нулю. Таким образом, внутренний NVL также необходим в альтернативном наборе значения по умолчанию 0 для столбца.

...