我想基于来自另一个现有表A的信息创建一个新的表B.我想知道MySQL是否具有考虑一系列时间和组列A值的功能然后只总结了值B列基于A列中的那些组。
表A存储用户日记等事件的日志。单个用户可以在一天内完成多个事件。假设我跟踪我的用户何时吃水果,我想知道他们一周(7天)吃多少水果以及他们吃多少苹果。
因此,在表B中,我想计算表A中的每个条目,前7天的水果和苹果总数。
编辑:
对不起,我简化了我给出的信息,并没有彻底想到我的例子。
我最初只有表A.我正在尝试从查询中创建表B.
假设:
总和计数超过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个苹果。
答案 0 :(得分:0)
假设:
那么这个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
有些问题:
答案 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