有没有更好的方法从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个。
答案 0 :(得分:10)
这种类型的查询可以在"最大-n-group-group"中重新定义。感觉,你想要每个"组"是'foo'的价值。
我建议您查看this link,这个问题非常精彩,从一种有意义的方式开始执行查询并逐步优化它。
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 ...
行。
基本上,内部查询(SELECT foo, score FROM tablebar WHERE foo IN ('abc','def') ORDER BY foo, score DESC
)从表格中抓取foo
和score
,先按foo
排序,然后按降序排列。
@num := ...
只会增加每一行,每foo
的新值重置为1。也就是说,@num
只是行号/排名(尝试单独运行内部查询以查看我的意思)。
外部查询然后选择排名/行号小于或等于10的行。
注:
使用UNION
的原始查询会删除重复项,因此如果foo='abc'
的前10个分数都是100,那么只返回一行(因为(foo,score)
对被复制10次)。这个将返回重复。