我正在尝试在MySQL中进行累积聚合。
我的原始数据如下所示:(我的日期是月/日/年)
user_id created_at source
1 1/1/01 foo
2 1/1/01 foo
3 1/2/01 bar
4 1/2/01 foo
5 1/3/01 foo
....
鉴于此,我想做一个看起来像这样的结果:
date source total_in_source
1/1/01 foo 2
1/2/01 foo 3
1/3/01 foo 4
其中total_in_source是第一个和当前日期值之间created_at的用户数的总和。
我可以使用相关的子查询来做到这一点,但这有点低效:
select
date(user.created_at) d,
user.source as user_source,
(select count(*) from users u where u.source = user_source and month(u.created_at) <= month_joined) as total_users_source,
from users user group by d, user_source
我做了一些环顾四周,似乎这样做可能是朝着正确方向迈出的一步:
select date(u1.created_at) as 'd',
u1.source as 'source',
count(distinct u2.id) as count_users
from users u1, users u2
where
u2.created_at BETWEEN DATE(u1.created_at) AND DATE_ADD(DATE(u1.created_at), interval 1 day) and
group by d, source
但即使这是一个自连接并产生n ^ 2行来迭代(用户*用户)。有关于如何做到这一点的最佳实践吗?
提前感谢。
答案 0 :(得分:1)
您需要“人工创建”在临时表或直接内联中加入的开始日期和结束日期。
假设您希望开始,结束月份的每个组合,然后在该时间范围内按照您所描述的来源和计数进行细分。你可以这样做:
从用户中选择u.source,sdates.val start,edates.val end,count(*)from(select distinct(date(created_at))val,其中day(created_at)= 1)sdates join(select distinct(date) (created_at))来自用户的val,其中day(created_at)= 1)通过sdates.val,edates.val,u.source;
编辑sdates.val和edates.val group之间的u.created_at上的用户u。基本上,内部查询“获取日期”,外部查询实际上进行计算。对于项目的每个相关日期,有一个“日期”表可能会有所帮助,因此您可以轻松地加入它而不必执行此伏都教,但如果没有这样做,这似乎有效。< / p>
此外,您可能不希望开始和结束的每个组合,因此您可以使用内部查询的“where”条件或连接的“on”来满足您的需要。
好奇,如果有人有更好的解决方案。