MySQL查询基于滑动窗口中的时间范围,组用户和总和值

时间:2013-09-09 18:30:44

标签: mysql

我想基于来自另一个现有表A的信息创建一个新的表B.我想知道MySQL是否具有考虑一系列时间和组列A值的功能然后只总结了值B列基于A列中的那些组。

表A存储用户日记等事件的日志。单个用户可以在一天内完成多个事件。假设我跟踪我的用户何时吃水果,我想知道他们一周(7天)吃多少水果以及他们吃多少苹果。

因此,在表B中,我想计算表A中的每个条目,前7天的水果和苹果总数。

编辑:
对不起,我简化了我给出的信息,并没有彻底想到我的例子。

我最初只有表A.我正在尝试从查询中创建表B.

假设:

  • 用户/ id可以在一天内多次记录条目。
  • 总和计数应为日期和日期之间的ID - 7天
  • 水果柱代表7天间隔期间的水果总数(苹果和香蕉都是水果)
  • 数据不仅从2013-9-5开始。它可以追溯到2000年,我希望在2000年至2013年的所有日期使用7天的推拉窗口。

总和计数超过7天的滑动窗口

以下是一个例子:

Table A:                           

| id | date-time          | apples | banana |     
---------------------------------------------
|  1 | 2013-9-5 08:00:00  |   1    |   1    |  
|  2 | 2013-9-5 09:00:00  |   1    |   0    |   
|  1 | 2013-9-5 16:00:00  |   1    |   0    |  
|  1 | 2013-9-6 08:00:00  |   0    |   1    |    
|  2 | 2013-9-9 08:00:00  |   1    |   1    |  
|  1 | 2013-9-11 08:00:00 |   0    |   1    |   
|  1 | 2013-9-12 08:00:00 |   0    |   1    |   
|  2 | 2013-9-13 08:00:00 |   1    |   1    |  

注意:用户1在2013-9-5上记录了2个条目

查询后的结果应为表B.

Table B
| id | date-time          | apples | fruit  |
--------------------------------------------
|  1 | 2013-9-5 08:00:00  |   1    |   2    |
|  2 | 2013-9-5 09:00:00  |   1    |   1    |
|  1 | 2013-9-5 16:00:00  |   2    |   3    |
|  1 | 2013-9-6 08:00:00  |   2    |   4    |
|  2 | 2013-9-9 08:00:00  |   2    |   3    |
|  1 | 2013-9-11 08:00:00 |   2    |   5    |
|  1 | 2013-9-12 08:00:00 |   0    |   3    |
|  2 | 2013-9-13 08:00:00 |   2    |   4    |

在2013-9-12,滑动窗口移动,仅包括9-6到9-12。这就是为什么id 1从2个苹果的总和变为0个苹果。

2 个答案:

答案 0 :(得分:0)

假设:

  • 每个ID /日期一行
  • 计数应为日期和日期之间的ID - 7天
  • “fruit”=“banana”
  • “日期”列实际上是日期(包括年份)而不仅仅是月/日

那么这个SQL应该可以解决这个问题:

INSERT INTO B
SELECT a1.id, a1.date, SUM( a2.banana ), SUM( a2.apples )
  FROM (SELECT DISTINCT id, date
          FROM A
         WHERE date > NOW() - INTERVAL 7 DAY
       ) a1
  JOIN A a2
    ON a2.id    = a1.id
   AND a2.date <= a1.date
   AND a2.date >= a1.date - INTERVAL 7 DAY
 GROUP BY a1.id, a1.date

有些问题:

  • 上述假设是否正确?
  • 表A包含的水果多于香蕉和苹果吗?如果是这样,真实结构是什么样的?

答案 1 :(得分:0)

您的数据需要多年才能正确使用日期算术。我加了他们。

您的数据中有一件奇怪的事情。您似乎每天都有多个日志条目供每个人使用。你假设一个隐含的顺序设置后面的日志条目以某种方式“在”之前的日志条目。如果SQL和MySQL这样做,那只是偶然的:表中没有行的隐式排序。另外,如果我们复制日期/ id组合,自联接(读取)有很多重复的行并且会破坏总和。

因此,我们需要首先创建数据的每日汇总表,如下所示:

    select id, `date`, sum(apples) as apples, sum(banana) as banana
      from fruit
     group by id, `date`

此摘要每个ID每天最多包含一行。

接下来我们需要做一个有限的交叉产品自我加入,所以我们得到七天的水果吃。

select --whatever--
 from (
    -- summary query --
 ) as a  
  join (
    -- same summary query once again
 ) as b   
    on (      a.id = b.id 
         and  b.`date` between a.`date` - interval 6 day AND a.`date`   )

between中的on条款为我们提供了七天(今天和之前的六天)。请注意,使用别名b的联接中的表是七天的内容,而a表是今天的内容。

最后,我们必须根据您的规范总结该结果。生成的查询就是这个。

  select a.id, a.`date`,
       sum(b.apples) + sum(b.banana) as fruit_last_week,
       a.apples as apple_today
  from (
        select id, `date`, sum(apples) as apples, sum(banana) as banana
          from fruit
         group by id, `date`
     ) as a  
  join (
        select id, `date`, sum(apples) as apples, sum(banana) as banana
          from fruit
         group by id, `date`
     ) as b   on (a.id = b.id and 
                      b.`date` between a.`date` - interval 6 day AND a.`date`   )
  group by a.id, a.`date`, a.apples
  order by a.`date`, a.id

这是一个小提琴:http://sqlfiddle.com/#!2/670b2/15/0