【发布时间】:2015-02-04 08:53:58
【问题描述】:
我有 3 张桌子。具有以下结构的用户、消息和用户分析:
- user (userId) - 包含所有用户
- message (messageId(pk),userId(fk),time) - 包含所有消息
- user_analytics (user_analyticsId(pk),userId(fk),device,time) -
包含在连接时收集的数据
user : messages (1:n) user : device (1:n)
现在我想知道每天使用什么设备发送了多少条消息。因此,我首先需要根据消息时间本身收集用于发送消息的设备(桌面、iOS、Android)的每条消息。这意味着我需要 user_analytics.time
我看到了很多关于 best-n-per-group 的解决方案,但我没有让它发挥作用。
我只让它与一个需要 20 秒的子查询一起工作(user_analytics 拥有 100k 条记录和 3k 条消息......所以不多):
select date_format(m.time,'%Y-%m-%d') as date,
count(*) as message_count,
ua.device
from message m,
user u left join user_analytics ua on (
u.userId = ua.userId and
ua.user_analyticsId = ( select max(user_analyticsId)
from user_analytics
where userId = m.userId and
time < m.time))
where m.userId = u.userId
group by 1,3;
但这看起来非常低效。还有其他方法可以达到同样的效果吗?
更新: 我忘了提到我在用户表上有一个重要条件。这就是为什么我需要加入这个表。
我创建了一个 sql fiddle 给你一个例子。现在我已经实现了Jaguar Chang's 解决方案,它比我的快 100 倍:
【问题讨论】:
-
在我回答问题之前,我需要您解决一些含糊不清的问题。如果您只想“现在每天使用什么设备发送多少条消息”,您的查询似乎没有回答这个问题。您能否更明确地说明您要获得哪些数据?接下来,这个“user_analytics.time
-
改用不相关的子查询
-
下面的答案看起来不错,但要获得更多帮助,请考虑遵循这个简单的两步操作过程: 1. 如果您还没有这样做,请提供适当的 DDL(和/或 sqlfiddle),以便我们可以更容易地复制问题。 2. 如果您尚未这样做,请提供与步骤 1 中提供的信息相对应的所需结果集。
-
"这比我的快 100 倍:" 并产生预期的结果?
-
@Strawberry:是的,现在需要 0.7 秒(所以感觉是之前的 20 秒的 100 倍)我想知道当数据增长时它会如何执行。