2013-07-16 17 views
25

Mi piacerebbe eseguire la divisione in una clausola SELECT. Quando faccio parte di alcune tabelle e utilizzo la funzione di aggregazione, ho spesso valori nulli o zero come divisori. Per ora mi viene in mente questo metodo per evitare la divisione per zero e valori nulli.Evita la divisione per zero in PostgreSQL

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

Mi chiedo se esiste un modo migliore per farlo?

+4

La divisione per un valore nullo non è un problema nel modo in cui la divisione per zero è. A proposito, count() non restituisce mai null. –

+0

Non lo sapevo! grazie per le informazioni. – William

risposta

24

Dal count() non restituisce mai NULL (a differenza di altre funzioni di aggregazione), si hanno solo per catturare il caso 0 (che è l'unico caso problematico comunque):

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

Quoting the manual about aggregate functions:

Va notato che, ad eccezione count, queste funzioni restituiscono un valore nullo quando nessuna riga è selezionata.

+0

grazie per il link, non ne ero a conoscenza +1 :) – Akash

92

È possibile utilizzare la funzione NULLIF, ad es.

something/NULLIF(column_name,0) 

Se il valore di column_name è 0 - risultato di intera espressione sarà NULL

+7

qualcosa di simile valore/COALESCE (NULLIF (column_name, 0), 1) funzionerebbe suppongo – Akash

+0

Provato con COALESCE come suggerito da @Akash e ha funzionato il lavoro –

+1

NULLIF funziona esattamente come suggerito da Yuiry - grazie! –

1

Se si desidera che il divisore per essere 1 quando il conteggio è pari a zero:

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

Il cast da true a integer è 1.

+0

Bel trucco, ma penso che una dichiarazione di un caso potrebbe essere più ovvia. –

+0

'CASE' è anche più veloce, anche se più dettagliato. –

12

Mi rendo conto che è una vecchia questione, ma un'altra soluzione potrebbe essere quella di utilizzare la funzione di grande:

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

Nota: La mia preferenza sarebbe quella di o restituire un NULL, come nella risposta di Erwin e Yuriy, o per risolvere questo logicamente rilevando il valore è 0 prima dell'operazione di divisione e restituendo 0. In caso contrario, i dati potrebbero essere rappresentati in modo errato utilizzando 1.

+0

Lo userò, poiché il mio divisore è un "tempo trascorso" per un processo, e 0 probabilmente significa una frazione di secondo, quindi Userò 0,01 minuti come tempo predefinito. Sto solo confrontando le prestazioni del processo. – PhilHibbs