有没有更有效的方法从每个组中获取前 X 个结果?
您可以忽略查询中未使用的 sqlfiddle 中的任何字段。
查询:
SET @num := 0, @item_id := '';
SELECT `item_id`, `user_id`, total_hoarded FROM (
SELECT `item_id`, `user_id`, total_hoarded,
@num := IF(@item_id = x.`item_id`, @num + 1, 1) AS ROW_NUMBER,
@item_id := x.`item_id` AS dummy
FROM (
SELECT `item_id`, `user_id`, COUNT(*) AS total_hoarded
FROM `player_items`
GROUP BY `item_id`, `user_id`
ORDER BY `item_id`, total_hoarded DESC
) AS x
) AS y WHERE y.ROW_NUMBER <= 10;");
演示:http ://sqlfiddle.com/#!2/75bc7/1
查询说明:
(从最嵌套的查询开始)它通过 item_id 和 user_id 抓取并分组所有行,以便我们可以做一些聚合函数来计算每个用户有多少项目。
下一级然后将 row_number 附加到每一行,以便最终查询可以简单地获取小于 X 的所有行(在这种情况下,每个分组的前 10 个用户)。
SQLFiddle 在样本的大小方面受到限制,因此它只显示两个项目和少数用户的数据。不足以完全进入前 10 名,但足以说明我在做什么。
选项(我正在考虑):
- 保持原样查询。
- 做一个标准的查询分组并通过 PHP 循环获取前 10 名
- 其他?(其他的还没想好)
备注:
我意识到我可能没有提供足够的细节,所以让我知道你需要什么。我只是在寻找一种通用的方法来解决这个问题。上面的查询在 30mill 行的表上运行大约需要 5 分钟。不过这没什么大不了的,因为查询每小时只运行一次。
将查询分成更小的部分可能会运行得更快,但表会被写入很多内容,因此查询往往会被锁定。