2011-06-29 4 views
7

Chciałbym agregatów pustym wyniku ustawiona na 0. Próbowałem następujące:łączna pustym wyniku ustawić

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

Wynik:

sum 
----- 

(1 row) 

Subquestion: nie powyższe prace w Oracle, używając SUM(NVL(capacity, 0))?

+0

Jaki błąd dostałeś? –

Odpowiedz

8

Od the documentation page o zagregowane funkcje:

Należy zauważyć, że z wyjątkiem count, funkcje te zwraca wartość null, gdy nie wiersze są wybierane. W szczególności, sum bez wierszy zwraca zero, a nie zero, jak można się spodziewać. Funkcja coalesce może być użyta do zastąpienia wartości zerowej w razie potrzeby wartością zerową.

Tak więc, jeśli chcesz, aby zagwarantować wartość zwracana, stosuje COALESCE do wyniku z SUM, a nie do jego argumentacji:

SELECT COALESCE(SUM(capacity), 0) … 

chodzi o 'subquestion' Wyroczni dobrze, nie znaleziono żadnej pojęcie wartości null na oficjalnej stronie doc (the one for 10.2, w szczególności), ale dwa inne źródła są jednoznaczne:

Oznacza to, że nie trzeba stosować NVL do capacity. (. Ale, jak z COALESCE w PostgreSQL, możesz chcieć, aby zastosować go do SUM)

+0

Czy nie należy "zastępować wartości zerowej za zero" zamiast zacytować ', aby zastąpić zero wartością zerową? Nie jestem jednak native speakerem. –

+0

@ VlastimilOvčáčík: Ja też. Mam nadzieję, że ktokolwiek napisał ten fragment w dokumentach, był! :) Poważnie jednak, to zdanie jest poprawne po angielsku. "Substytut A dla B" oznacza to samo, co "zastąpić * lub * zastąpić B przez A". Gramatyka angielska - idź! –

+0

Jesteś [w prawo] (http://english.stackexchange.com/questions/23360/substitute-x-for-y)! Ale jest to trudne. –

5

Chodzi o to, że agregat zawsze zwraca wiersz, nawet jeśli nie zostały zebrane żadne wiersze (tak jak w zapytaniu). Zsumowałeś wyrażenie bez żadnych wierszy. Stąd otrzymujesz wartość zerową.

Spróbuj to zamiast:

select coalesce(sum(capacity),0) 
from objects 
where false; 
+1

można uprościć to z koalescją (suma (pojemność), 0), ponieważ sum() zignoruje wartości NULL. – peufeu

+0

@peufeu: true, ale jeśli jego faktyczna kwerenda używa lewego sprzężenia, null + cokolwiek daje wartość null, podobnie jak suma z potencjalnie pustym polem. –

+1

peufeu ma rację. Koalescencja wewnątrz SUM jest zbędna. Zobacz symulację kodu mojej odpowiedzi –

1

Wystarczy to zrobić:

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

Nawiasem mówiąc, COALESCE wewnątrz suma jest zbędny, nawet jeśli pojemność jest NULL , nie sprawi, że podsumowanie null.

słownie:

create table objects 
(
    capacity int null 
); 

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

select sum(capacity) from objects; 

To zwróci wartość 6, NOT NULL.

A koalescencja wewnątrz funkcji agregującej jest także zabójczy dla wydajności, ponieważ twój silnik RDBMS nie może po prostu zgrać przez wszystkie wiersze, musi ocenić kolumnę każdego wiersza, jeśli jej wartość jest pusta. Widziałem trochę kwerendy OCD, gdzie wszystkie zagregowane zapytania mają koalesce wewnątrz, myślę, że oryginalne dev ma objaw Cargo Cult Programming, kwerenda jest bardzo bardzo sloooowww. Usunąłem koalescję wewnątrz SUMY, a zapytanie stało się szybkie.

0

Chociaż ten post jest bardzo stary, ale chciałbym, aby aktualizować co mogę użyć w takich przypadkach

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

Tutaj zewnętrzny NVL uniknąć przypadków, gdy nie ma wiersz w zestawie wyników. Wewnętrzna NVL jest używana dla zerowych wartości kolumn, należy rozważyć przypadek (1 + null), a wynik będzie zerowy. Zatem wewnętrzna NVL jest również potrzebna w innych alternatywnych ustawieniach domyślnej wartości 0 do kolumny.