Как выбрать sum -or- 0, если нет записей - PullRequest
30 голосов
/ 17 января 2012

Мне нужно написать запрос, который возвращает сумму всех значений, соответствующих определенным критериям, но запрос должен возвращать 0, если строки не найдены, а не ноль.Например:

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

Этот запрос:

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

должен возвращать 15.Однако:

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

должен возвращать 0, но возвращает null.

Может кто-нибудь объяснить, возможно ли это?

Ответы [ 4 ]

66 голосов
/ 17 января 2012

Как насчет:

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

Функция COALESCE в основном говорит: «вернуть первый параметр, если только он не равен нулю, в этом случае вернуть второй параметр» - это довольно удобно в этих сценариях.

9 голосов
/ 17 января 2012

Проверьте документацию MySQL для IFNULL .

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

Конечно, это предполагает, что ваше поле num имеет значение NULL и не имеет значения по умолчанию.Другим возможным решением было бы установить значение по умолчанию 0 для поля num, которое должно решить вашу проблему.

3 голосов
/ 11 ноября 2017

Чтобы сделать это правильно, вы можете различить случай, когда есть действительные NULL результаты в суммируемых вами данных, и случай, когда нет значений для суммирования.

Предположим, у нас есть следующее:

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

Мы бы хотели, чтобы пустые суммы были равны нулю, но суммы с NULL равны NULL. Один (довольно мучительный) способ сделать это:

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)

Возможно, есть лучший способ, о котором я не думал.

К сожалению, стандарт SQL определяет SUM как ноль, когда никакие элементы не суммируются , и у MySQL нет иного выбора, кроме как следовать этому стандарту.

1 голос
/ 17 января 2012

Это работает:

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

IF () принимает три параметра: (1) оператор, (2) значение, применяемое, если утверждение верно, и (3) значение, применяемое, если утверждение является ложным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...