MySQL:由10个最近活跃的用户选择5个操作
假设一个名为activity的表包含以下列: 何时发生日期时间,谁发短信,什么短信 我想选择最近一个小时内10个最近活跃用户的5个最新操作 到目前为止,我已经:MySQL:由10个最近活跃的用户选择5个操作,mysql,Mysql,假设一个名为activity的表包含以下列: 何时发生日期时间,谁发短信,什么短信 我想选择最近一个小时内10个最近活跃用户的5个最新操作 到目前为止,我已经: SELECT * FROM activity JOIN ( SELECT who FROM activity WHERE whenItHappened >= (CURDATE()- INTERVAL 1 HOUR) GROUP BY (who) ORDER BY whenItHappened DES
SELECT * FROM activity
JOIN (
SELECT who FROM activity
WHERE whenItHappened >= (CURDATE()- INTERVAL 1 HOUR)
GROUP BY (who)
ORDER BY whenItHappened DESC
LIMIT 10
) AS unique_recent_users
ON unique_recent_users.who = activity.who;
这很好地选择了最近十个活跃用户的所有活动。但是,我想不出一个好办法来限制每个用户的最后五个动作
如果我在SQL语句的末尾放一个LIMIT子句,它总共只返回五个结果。理想的行为是,如果在最后一个小时内有10个用户处于活动状态,那么它应该显示50个操作,其中每个最近处于活动状态的用户有5个操作
我可以很容易地做到这一点,通过使用PHP对一个查询获取最近的10个用户,然后每个用户执行5个操作,但我不禁想,在MySQL中,一定有一些优雅的方法可以实现这一点
编辑:通过Darrrren的链接,我找到了这个解决方案,它允许我从所有用户中选择5个最新的操作。我不确定随着桌子越来越大,表演会是什么样子
select whenItHappened, who, what
from activity
where (
select count(*) from activity as a
where a.who = activity.who and a.whenItHappened <= activity.whenItHappened
) <= 5;
在MySQL中无法优雅地实现这一点。一种有效的方法需要自联接:
select a.*
from (SELECT who
FROM activity
WHERE whenItHappened >= (CURDATE()- INTERVAL 1 HOUR)
GROUP BY (who)
ORDER BY whenItHappened DESC
LIMIT 10
) AS unique_recent_users join
Activity a
on unique_recent_users.who = activity.who join
Activity a2
on a2.who = a.who and
a2.whenItHappened >= a.WhenItHappened
group by a.id
having count(*) <= 5
注意,这是使用MySQL的Hidden Columns特性返回group by语句中未包含的列
如果每个用户的活动表中碰巧有一个计数器,则可以使用此计数器获取最近的五个计数器。如果你想要50个最新的活动,不管用户是谁,你也可以这样做。而且,如果您使用的几乎是任何其他数据库,那么排名函数(尤其是行数)将优雅地解决问题。这不是一个答案,但应该会让您上路:非常有趣,我将尝试一下。同样从Darrren的链接中,我发现了一种似乎有效的技术,尽管我不确定随着表格变大,性能会如何。选择WhenItocated,who,what from activity where选择count*from activity as a where a.who=activity.who和a.whenItocated我发现关于用户变量的文档对于它们是否保证可以用于枚举行的定义不明确。在实践中,它们似乎是有效的,而且这种方法在处理大量数据时应该更快。在任何一种情况下,您都应该有一个索引,说明何时优化性能。文档中的具体行是:作为一般规则,您不应该为用户变量赋值,而应该在同一语句中读取值。你可能会得到你期望的结果,但这不是保证。但是,这些示例似乎引用了在不同表达式中使用的变量,因此不清楚建议是否适用于在单个表达式中使用的变量。好的,很有趣。我有关于谁和何时发生的索引。我不熟悉那些关于用户变量的指导原则。