如果不存在记录,如何选择 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