假设一个名为“activity”的表,其中包含以下列:
whenItHapned datetime,who text,what text
我想在过去一小时内选择10个最近活跃用户的5个最新动作。
到目前为止,我有:
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子句,它将只返回五个结果。理想的行为是,如果在过去一小时内有十个用户处于活动状态,则应显示50个操作,每个最近活动的用户都有五个。
我可以通过将PHP用于一个查询来获取最新的10个用户,然后从每个用户执行5个操作,但我不禁想到必须有一些优雅的方式在MySQL本地执行此操作
编辑(通过Darrrrren的链接我找到了这个解决方案,它允许我从所有用户中选择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;
答案 0 :(得分:0)
在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的隐藏列“功能”来返回group by
语句中未包含的列。)
如果您在每个用户的活动表中碰巧有一个计数器,那么您可以使用此计数器获取最近的五个。如果您想要50个最近的活动,无论用户如何,您也可以这样做。而且,如果您使用几乎任何其他数据库,那么排名函数(特别是row_number()
)将优雅地解决问题。