2013-07-16 32 views
25

Chciałbym dokonać podziału w klauzuli SELECT. Kiedy dołączam do niektórych tabel i używam funkcji agregacji, często jako wartości dzielące mam wartości zerowe lub zerowe. Na razie tylko wymyślam tę metodę unikania dzielenia przez zero i wartości zerowe.Unikaj dzielenia przez zero w PostgreSQL

(CASE(COALESCE(COUNT(column_name),1)) WHEN 0 THEN 1 
ELSE (COALESCE(COUNT(column_name),1)) END) 

Zastanawiam się, czy istnieje lepszy sposób na zrobienie tego?

+4

Podział według wartości zerowej nie stanowi problemu w rozumieniu podziału na zero. Nawiasem mówiąc, count() nigdy nie zwraca wartości null. –

+0

Nie wiedziałem o tym! dzięki za informację. – William

Odpowiedz

24

Od count() nigdy nie powraca NULL (w przeciwieństwie do innych funkcji agregujących), trzeba tylko złapać sprawę 0 (który jest jedynym problematyczna sprawa tak):

CASE count(column_name) 
    WHEN 0 THEN 1 
    ELSE count(column_name) 
END 

Quoting the manual about aggregate functions:

Należy zauważyć, że z wyjątkiem count, te funkcje zwracają wartość null , gdy nie są wybrane żadne wiersze.

+0

dziękuję za link, nie wiedziałem o tym +1 :) – Akash

92

Można użyć funkcji NULLIF np.

something/NULLIF(column_name,0) 

Jeżeli wartość column_name wynosi 0 - wynik całego wyrażenia będzie NULL

+7

coś wartości/COALESCE (NULLIF (column_name, 0), 1) będzie działać Przypuszczam – Akash

+0

próbował go z COALESCE jak @Akash sugerowane i to miało pracę –

+1

NULLIF działa dokładnie tak jak sugeruje Yuiry - dzięki! –

1

Jeśli chcesz dzielnik wynosi 1, gdy liczba jest równa zero:

count(column_name) + 1 * (count(column_name) = 0)::integer 

Obsada od true do integer jest 1.

+0

Dobra sztuczka, ale myślę, że stwierdzenie sprawy może być bardziej oczywiste. –

+0

'CASE' jest również szybsze, nawet jeśli jest bardziej szczegółowe. –

12

Zdaję sobie sprawę, że jest to stare pytanie, ale innym rozwiązaniem byłoby skorzystać z funkcji największym:

greatest(count(column_name), 1) -- NULL and 0 are valid argument values 

Uwaga: Moje preferencje byłoby albo zwróć wartość NULL, jak w odpowiedzi Erwina i Yuriya, albo rozwiązaj to logicznie, wykrywając wartość 0 przed operacją dzielenia i zwracając 0. W przeciwnym razie dane mogą zostać błędnie przedstawione za pomocą 1.

+0

Użyję tego, ponieważ mój dzielnik to "upływający czas" dla procesu, a 0 prawdopodobnie oznacza ułamek sekundy, więc Użyję domyślnie czasu 0,01 minuty. Porównuję wydajność procesu. – PhilHibbs