web-dev-qa-db-fra.com

Eviter la division par zéro dans PostgreSQL

Je voudrais effectuer la division dans une clause SELECT. Lorsque je joins certaines tables et que j'utilise la fonction d'agrégat, j'ai souvent des valeurs nulles ou nulles comme séparateurs. Pour l'instant, je ne propose que cette méthode pour éviter la division par zéro et les valeurs nulles. 

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

Je me demande s'il y a une meilleure façon de faire cela?

40
William

Puisque count() NE RETOURNE JAMAIS NULL (contrairement aux autres fonctions d'agrégat), il vous suffit d'attraper le cas 0 (qui est le seul cas problématique de toute façon):

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

Citation du manuel sur les fonctions d'agrégat:

Il est à noter que sauf pour count, ces fonctions renvoient un Valeur nulle quand aucune ligne n'est sélectionnée.

28
Erwin Brandstetter

Vous pouvez utiliser la fonction NULLIF, par exemple.

something/NULLIF(column_name,0)

Si la valeur de column_name est 0, le résultat de l'expression entière sera NULL

131
Yuriy Galanter

Je réalise que c’est une vieille question, mais une autre solution consisterait à utiliser la fonction greatest:

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

Remarque: .__ Ma préférence serait de renvoyer une valeur NULL, comme dans la réponse de Erwin et Yuriy, ou de résoudre ce problème de manière logique en détectant que la valeur est 0 avant l'opération de division et renvoyer 0. Sinon, les données risquent d'être mal représentées en utilisant 1.

21
vol7ron

Une autre solution en évitant seulement la division par zéro, en changeant la division par 1

select column + (column = 0)::integer;
1
Manvel

Si vous voulez que le diviseur soit égal à 1 lorsque le compte est égal à zéro:

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

La distribution de true à integer est 1.

1
Clodoaldo Neto