如果不存在记录,如何选择 sum -or- 0?

Posted

技术标签:

【中文标题】如果不存在记录,如何选择 sum -or- 0?【英文标题】:How to select sum -or- 0 if no records exist? 【发布时间】:2012-02-11 21:19:57 【问题描述】:

我需要编写一个查询,返回满足某个条件的所有值的总和,但是如果没有找到行,则该查询需要返回 0,而不是 null。例如:

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

有人可以解释一下吗?

【问题讨论】:

【参考方案1】:

简短的方法是:

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

【讨论】:

【参考方案2】:

要正确执行此操作,您可能需要区分实际 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 标准defines SUM to be null when no elements are summed,MySQL 只能遵循该标准。

【讨论】:

【参考方案3】:

检查MySQL documentation for IFNULL。

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

当然,这假设您的num 字段可以为空并且没有默认值。另一种可能的解决方案是为 num 字段设置默认值 0,这应该可以解决您遇到的问题。

【讨论】:

IFNULL 应该在 SUM 之外,否则如果没有找到行将返回 null。 SUM 已经忽略了 NULL 值。在所有情况下 SUM(IFNULL(abc, 0)) == SUM(abc) @Eloims 您的评论似乎是错误的。我也假设过,但这是错误的,这就是我在这里寻找答案的原因。 @ChadBefus 我确实错了。 SUM 将忽略 NULL,但如果列仅包含 null,或者表为空,则返回 NULL。这是一个测试这个的小提琴:db-fiddle.com/f/5hvBkzyMWKYx7mT6hKqKFS/0【参考方案4】:

这行得通:

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

IF() 采用三个参数:(1) 语句,(2) 如果语句为真则应用的值,以及 (3) 如果语句为假则应用的值。

【讨论】:

【参考方案5】:

怎么样:

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

COALESCE 函数基本上说“返回第一个参数,除非它为 null,在这种情况下返回第二个参数”——在这些场景中非常方便。

【讨论】:

这实际上并没有达到预期的效果——这也会掩盖NULL,它是num值本身的一部分。 这不起作用。如果没有要聚合的行 coalesce 甚至不会被调用。我不明白这怎么会有 122 票。

以上是关于如果不存在记录,如何选择 sum -or- 0?的主要内容,如果未能解决你的问题,请参考以下文章

[pat]1007 Maximum Subsequence Sum

从 MySQL 中的两个视图中选择而不留下记录

SQL-如果指定值存在返回1,如果不存在返回0的SQL语句

t-sql 如果记录存在则选择一列,如果不存在则选择不同的列

如何检查刀片中是不是存在记录?

如何在SQL Server2005数据库中检查一个表是不是存在,如存在就删除表记录,如不存在就建表.