是否有更好的方法从MySQL表中获取多个“前X个”结果?当不同的 foo 的数量很少时,我可以通过联合轻松地完成此操作:
(SELECT foo,score FROM tablebar WHERE (foo = 'abc') ORDER BY score DESC LIMIT 10) UNION (SELECT foo,score FROM tablebar WHERE (foo = 'def') ORDER BY score DESC LIMIT 10)
我显然可以继续为foo的每个值添加联合。但是,当foo有500多个不同的值并且我需要每个值的前X个时,这是不切实际的。
这种查询可以用“每组最大n”来表述,您希望每个“组”的前10个得分为“ foo”。
我建议您看一下这个链接,它很好地处理了这个问题,从一种有意义的方式开始执行您的查询并逐步优化它。
set @num := 0, @foo := ''; select foo, score from ( select foo, score, @num := if(@foo = foo, @num + 1, 1) as row_number, @foo := foo as dummy from tablebar where foo IN ('abc','def') order by foo, score DESC ) as x where x.row_number <= 10;
如果您想在 所有 级别上执行此操作foo(即,假设执行GROUP BY foo),则可以省略该where foo in ...行。
foo
GROUP BY foo
where foo in ...
基本上,内部查询(SELECT foo, score FROM tablebar WHERE foo IN ('abc','def') ORDER BY foo, score DESC)抓住foo并score从该表中,由第一排序foo,然后评分降序。
SELECT foo, score FROM tablebar WHERE foo IN ('abc','def') ORDER BY foo, score DESC
score
在@num := ...刚刚增加的每一行,重置为1的每个新值foo。也就是说,@num仅是行号/行数(尝试自行运行内部查询以了解我的意思)。
@num := ...
@num
然后,外部查询选择行/行数小于或等于10的行。
注意:
您的原始查询UNION会删除重复项,因此,如果前10个分数foo='abc'全为100,则仅返回一行(因为该(foo,score)对重复了10次)。这将返回重复项。
UNION
foo='abc'
(foo,score)