首页 > 解决方案 > SQL SUM 和 GROUP BY

问题描述

我不明白为什么 SQL 给我两个非常不同的数字,用于计算表中的值的简单 GROUP BY。我正在使用 2 列的 SUM。

我将尝试将其分解为系统中最简单的关键组件。

Ledger:  
| increase | decrease | userid | currency

Users:  
| email | role |

userid在 users 表上是 FK id,没有孤立行。

现在进行查询:

SELECT 
  SUM(l.increase) - SUM(l.decrease) as total
FROM ledger l 
JOIN users u ON l.userid = u.id AND u.role = 'customer'
WHERE l.currency = 'USD'
GROUP BY u.email
ORDER BY total DESC

以上产生了 145 行用户。我可以把它放在一个子查询中以获得我认为是真正的 SUM

SELECT SUM(tmp.total) FROM (<ABOVE_AS_SUBQUERY>) as tmp

我得到8042

这是我的第二个查询:

SELECT 
  SUM(l.increase) - SUM(l.decrease) as total
FROM ledger l 
JOIN users u ON l.userid = u.id AND u.role = 'customer'
WHERE l.currency = 'USD'
GROUP BY u.role
ORDER BY total DESC

这次我按角色分组,事实上,我可以将 GROUP BY 全部删除,它的行为是一样的。 我得到 99104

当然,结果应该是一样的。特别是因为我的加入条件已经在过滤role='customer'

GROUP BY u.email给了我一组独特的每封电子邮件的总数,但我不明白为什么删除 GROUP BY 给我的数字远远超出了 GROUP BY 之后数据集中的数字,显然正在发生一些奇怪的事情。为什么结果行不只是所有这些电子邮件的总和并给我 8042?

谢谢

编辑:这是一个SQL Fiddle。正如我最初预期的那样,这 2 个查询返回相同的结果。我无法在这个小提琴中复制这个问题,这意味着它与数据有关,但这里只有 2 个表在起作用。我可以使用什么样的数据来复制我所描述的内容?

标签: mysqlsqljoinaggregateaggregate-functions

解决方案


我会相信没有GROUP BY.

可能发生的是NULL价值观“干扰”了结果。 SUM()忽略NULL值,因此如果将所有非NULL值相加。但是,+不忽略NULL值。如果一操作数为NULL,则结果为NULL

例如,如果您有一个名称,其中所有decrease值都是NULL. 例如:

email    role     increase    decrease
  a       1          10         5
  b       1          20         NULL

在这个简单的示例中,通过电子邮件聚合将导致:

 a      5      -- 10 - 5 = 5
 b      NULL   -- 20 - NULL = NULL

但按角色,它将是:

 1      25     -- sum(10 + 20) - sum(5 + NULL) = 30 - 5 = 25

您没有NULL在问题中提及价值观,但它们可能是罪魁祸首。


推荐阅读