按日期分组的 MySQL 累积总和

Posted

技术标签:

【中文标题】按日期分组的 MySQL 累积总和【英文标题】:MySQL cumulative sum grouped by date 【发布时间】:2014-04-12 04:13:57 【问题描述】:

我知道有一些与此相关的帖子,但我的情况有点不同,我想在这方面获得一些帮助。

我需要从数据库中提取一些数据,这些数据是每天累积的交互次数。目前这就是我所拥有的

SELECT
   e.Date AS e_date,
   count(e.ID) AS num_interactions
FROM example AS e
JOIN example e1 ON e1.Date <= e.Date
GROUP BY e.Date;

这个输出接近我想要的,但不完全是我需要的。

我遇到的问题是日期与交互发生的小时分钟和秒一起存储,因此 group by 不会将日期分组在一起。

这是输出的样子。

在 12-23 有 5 次互动,但没有分组,因为时间戳不同。所以我需要想办法忽略时间戳,只看一天。

如果我尝试GROUP BY DAY(e.Date),它只会按天对数据进行分组(即任何一个月的 1 日发生的所有事情都被分组到一行中),而输出根本不是我想要的。

GROUP BY DAY(e.Date), MONTH(e.Date) 正在按月份和日期进行拆分,但计数再次关闭。

我根本不是 mysql 专家,所以我对自己缺少什么感到困惑

【问题讨论】:

【参考方案1】:

昨晚我想出了我需要做的事情......但由于我是新手,所以我无法发布它......我所做的工作是这样的:

SELECT
   DATE(e.Date) AS e_date,
   count(e.ID) AS num_daily_interactions,
   (
      SELECT 
         COUNT(id)
      FROM example 
      WHERE DATE(Date) <= e_date
   ) as total_interactions_per_day
FROM example AS e
GROUP BY e_date;

这会比您的查询效率低吗?如果效率更高,我可能会在提取每天的计数后在 python 中进行计算,因为这将返回数千到数十万行。

【讨论】:

您的查询看起来不错。只需确保您的日期比较符合您的预期,因为您将日期类型与日期时间类型进行比较。 响应是我想要的。我只是有点犹豫,因为随着这张桌子的增长它会很慢。再次感谢您所做的一切.. 非常有帮助 我会尝试解释这两个查询。我觉得这个会为每个日期运行子查询,如果我们有适当的索引,这应该不会很慢,但是@clheristian's 做了一个分组,然后迭代它,这可能会更好(特别是如果 -这是我的情况——你有额外的、非索引的过滤条件)。 @chesterbr 我最终更改了此查询,因为它需要一段时间。如果您查看我最近的问题,我会问一个关于优化它的问题.. 结束了两个查询,只是在 python 中进行累积计数...当将 300,000 条记录与自身进行比较时,查询开始需要 14-15 秒才能运行.. 有 90,000,000,000 行要检查.. 它的索引和优化仍然需要一些时间来比较。【参考方案2】:

新答案

起初,我不明白您是在尝试计算总和。下面是它的外观:

SET @runningTotal = 0;
SELECT 
    e_date,
    num_interactions,
    @runningTotal := @runningTotal + totals.num_interactions AS runningTotal
FROM
(SELECT 
    DATE(eDate) AS e_date,
    COUNT(*) AS num_interactions
FROM example AS e
GROUP BY DATE(e.Date)) totals
ORDER BY e_date;

原答案

由于您的加入,您可能会得到重复。也许 e1 对某些行有多个匹配项,这会增加您的计数。无论是那个还是你的连接中的比较也是比较秒,这不是你所期望的。

无论如何,不​​要将日期时间字段分割成天和月,只需从中去掉时间即可。以下是你的做法。

SELECT
   DATE(e.Date) AS e_date,
   count(e.ID) AS num_interactions
FROM example AS e
JOIN example e1 ON DATE(e1.Date) <= DATE(e.Date)
GROUP BY DATE(e.Date);

【讨论】:

感谢您的回复。剥离时间是我想要做的。我仍然没有得到正确的结果,所以我认为这与加入有关。我想要的是,如果第一天的计数是 3,然后第二天是 4,那么它在第二天显示 7(前一天与当前的累积量)。在 DATE() screencast.com/t/qcsRcZt7Ws4z 加入时,计数仍然会膨胀... 2013-12-23 上只有 5 次互动 .. 所以我想我需要寻找一种不同的方式来实现这一点。 所以连接的问题在于它将每条记录与所有可能的记录匹配。又名.. 如果有 5 个实例,则它与 1 匹配所有 5,然后下一个与所有 5 匹配,因此计数膨胀为 25 而不是 5。关于如何解决此问题的任何想法? 抱歉,我不明白您是在计算运行总计。我将添加到我的答案中 这很棒,因为即使处理大型数据集也能很好地工作 很好的答案@clhereistian(该表只读取一次)!谢谢,对我帮助很大。提示:如果您使用的 ORM(如 php 中的 Doctrine)每次执行只能接受一个查询:在子查询中将 SET @runningTotal = 0; 替换为 @runningTotal := 0, :) (此提示还可以帮助您/我进行多- 查询之间使用 UNION 的累积和)

以上是关于按日期分组的 MySQL 累积总和的主要内容,如果未能解决你的问题,请参考以下文章

MySQL查询根据按月分组的激活日期计算累积用户数

MS Access 按日期累积总和?

如何使用 sql 和按日期分组显示指标在日期上的累积增长?

MySql 累计总数按天分组在最大总数上

MySQL 累积总和取决于类型

如何创建按列分组的累积总和