Loại truy vấn này có thể được diễn đạt lại theo nghĩa "lớn nhất-n-mỗi nhóm", trong đó bạn muốn 10 điểm cao nhất cho mỗi "nhóm" là giá trị của 'foo'.
Tôi khuyên bạn nên xem liên kết này giải quyết câu hỏi này một cách tuyệt vời, bắt đầu bằng một cách phù hợp để thực hiện truy vấn của bạn và dần dần tối ưu hóa nó.
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;
Nếu bạn muốn thực hiện điều này trên tất cả cấp độ của foo
(tức là hãy tưởng tượng thực hiện một GROUP BY foo
), bạn có thể bỏ qua where foo in ...
dòng.
Về cơ bản, truy vấn bên trong (SELECT foo, score FROM tablebar WHERE foo IN ('abc','def') ORDER BY foo, score DESC
) lấy foo
và score
khỏi bảng, đặt hàng trước theo foo
và sau đó điểm số giảm dần.
@num := ...
chỉ tăng mỗi hàng, đặt lại thành 1 cho mỗi giá trị mới của foo
. Đó là, @num
chỉ là một số hàng / thứ hạng (hãy thử tự chạy truy vấn bên trong để xem ý tôi là gì).
Sau đó, truy vấn bên ngoài sẽ chọn các hàng có số thứ hạng / hàng nhỏ hơn hoặc bằng 10.
LƯU Ý:
Truy vấn ban đầu của bạn với UNION
loại bỏ các điểm trùng lặp, vì vậy nếu 10 điểm hàng đầu cho foo='abc'
tất cả đều là 100 thì chỉ một hàng sẽ được trả về (vì (foo,score)
cặp được lặp lại 10 lần). Cái này sẽ trả về các bản sao.