2012-01-17 8 views
18

Necesito escribir una consulta que devuelve la suma de todos los valores que cumplen ciertos criterios, pero la consulta debe devolver 0 si no se encuentran filas, en lugar de nulo. Por ejemplo:¿Cómo se selecciona suma -o bien - 0 si no existen registros?

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

Esta consulta:

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

debe, y lo hace, volver 15. Sin embargo:

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

deberían volver 0, pero lo hace volver null.

¿Alguien puede explicar si esto es posible?

Respuesta

44

¿Qué tal:

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

La función COALESCE básicamente dice "devolver el primer parámetro, a menos que sea nula, en cuyo caso devuelve el segundo parámetro" - Es muy útil en estos escenarios.

+0

Esto en realidad no tiene el efecto deseado, esto también enmascarará un 'NULL' que es parte de los valores 'num'. –

+0

Funciona, Gran solución – nitin

1

Esto funciona:

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

SI() toma tres parámetros: (1) Una declaración, (2) el valor de aplicarse si la afirmación es cierta, y (3) el valor de aplicar si el declaración es falsa

8

Compruebe el MySQL documentation for IFNULL.

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

Por supuesto, esto asume su campo num es anulable y no tiene un valor predeterminado. Otra posible solución sería establecer un valor predeterminado de 0 para el campo num que debería resolver el problema que está teniendo.

+6

IFNULL debe estar fuera de SUM; de lo contrario, si no se encuentran filas, devolverá nulo. –

0

Para hacer esto correctamente, es posible que desee distinguir entre el caso en el que hay resultados reales NULL en los datos que está sumando y el caso en el que no hay ningún valor para sumar.

Supongamos que tenemos el siguiente:

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

Quisiéramos sumas vacías a ser cero, pero que involucran sumas NULL ser NULL. Una forma (en lugar tortuoso) de hacerlo es:

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) 

Tal vez hay una mejor manera de que no he pensado.

Desafortunadamente, el estándar SQL defines SUM to be null when no elements are summed y MySQL no tienen más remedio que seguir ese estándar.

Cuestiones relacionadas