web-dev-qa-db-fra.com

Comment sélectionner somme -ou- 0 s'il n'existe aucun enregistrement?

J'ai besoin d'écrire une requête qui renvoie la somme de toutes les valeurs qui répondent à certains critères, mais la requête doit retourner 0 si aucune ligne n'est trouvée, plutôt que null. Par exemple:

tab    
+---------------+-----+
| descr         | num |
+---------------+-----+
| hello there   | 5   |
| hi there      | 10  |
| hello         | 10  |
| hi there!     | 15  |
+---------------+-----+

Cette requête:

SELECT sum(num) AS val FROM tab WHERE descr LIKE "%hello%";

doit renvoyer 15. Pourtant:

SELECT sum(num) AS val FROM tab WHERE descr LIKE "%greetings%";

devrait retourner 0, mais renvoie null.

Quelqu'un peut-il expliquer si cela est possible?

30
ewok

Que diriez-vous:

SELECT COALESCE(sum(num), 0) AS val FROM tab WHERE descr LIKE "%greetings%";

La fonction COALESCE dit essentiellement "retourne le premier paramètre, à moins qu'il ne soit nul auquel cas retourne le deuxième paramètre" - C'est assez pratique dans ces scénarios.

67
Mike Christensen

Vérifiez la documentation MySQL pour IFNULL .

SELECT SUM(IFNULL(num, 0)) as val FROM tab WHERE descr LIKE "%greetings%";

Bien sûr, cela suppose que votre champ num est nullable et n'a pas de valeur par défaut. Une autre solution possible serait de définir une valeur par défaut de 0 pour le champ num qui devrait résoudre le problème que vous rencontrez.

9
sesser

Pour le faire correctement, vous souhaiterez peut-être faire la distinction entre le cas où il y a des résultats réels de NULL dans les données que vous additionnez et le cas où il n'y a aucune valeur à additionner.

Supposons que nous ayons les éléments suivants:

mysql> select * from t;
+----------+------+
| descr    | num  |
+----------+------+
| hiya     |    5 |
| hi there |   10 |
| yo       | NULL |
+----------+------+

Nous aimerions que les sommes vides soient nulles, mais que les sommes impliquant NULL soient NULL. Une façon (plutôt tortueuse) de le faire est:

mysql> SELECT IF(has_null, NULL, total) AS sum FROM (
    ->    SELECT COALESCE(MAX(num IS NULL), 0) AS has_null, COALESCE(SUM(num), 0) AS total
    ->    FROM t WHERE num < 'ciao')
    -> AS u;
+------+
| sum  |
+------+
|    0 |
+------+
1 row in set, 1 warning (0.00 sec)

mysql> SELECT IF(has_null, NULL, total) AS sum FROM (
    ->    SELECT COALESCE(MAX(num IS NULL), 0) AS has_null, COALESCE(SUM(num), 0) AS total
    ->    FROM t)
    -> AS u;
+------+
| sum  |
+------+
| NULL |
+------+
1 row in set (0.00 sec)

mysql> SELECT IF(has_null, NULL, total) AS sum FROM (
    ->    SELECT COALESCE(MAX(num IS NULL), 0) AS has_null, COALESCE(SUM(num), 0) AS total
    ->    FROM t WHERE descr < 'namaste')
    -> AS u;
+------+
| sum  |
+------+
|   15 |
+------+
1 row in set (0.00 sec)

mysql> SELECT IF(has_null, NULL, total) AS sum FROM (
    ->    SELECT COALESCE(MAX(num IS NULL), 0) AS has_null, COALESCE(SUM(num), 0) AS total
    ->    FROM t WHERE descr > 'namaste')
    -> AS u;
+------+
| sum  |
+------+
| NULL |
+------+
1 row in set (0.00 sec)

Il y a peut-être une meilleure façon à laquelle je n'ai pas pensé.

Malheureusement, le standard SQL définit SUM comme étant nul quand aucun élément n'est sommé , et MySQL n'a pas d'autre choix que de suivre ce standard.

3
Ken Williams

Cela marche:

SELECT IF(SUM(num) IS NULL, 0, SUM(num)) AS val FROM tab WHERE descr LIKE "%whatever%";

IF () prend trois paramètres: (1) une déclaration, (2) la valeur à appliquer si la déclaration est vraie, et (3) la valeur à appliquer si la déclaration est fausse.

1
Thomas Kelley