No doubt everybody has solved it before, but ten seconds on Google didn’t show any obvious results, so here we go: How to pick the top 5 records of each group.
We’ll define “top 5” as “the first 5 records when ordering by a field called `rating`”.
For MySQL 8.0 and later, use the RANK() window function inside either a common table expression or a derived table:
WITH cte AS ( SELECT *, RANK() OVER(PARTITION BY groupId ORDER BY rating) AS rank FROM theTable ) SELECT * FROM cte WHERE rank <= 5;
5.7 and earlier didn’t have CTEs. Subqueries will suffice.
SELECT
theTable.*
FROM
theTable
JOIN (
SELECT
t1.groupId,
t1.rating,
COUNT(t2.groupId) AS theCount
FROM theTable t1
LEFT JOIN theTable t2 ON t1.groupId = t2.groupId AND t1.rating > t2.rating
GROUP BY t1.groupId, t1.rating
HAVING theCount < 5
) AS dt USING (groupId, rating);
Pre-4.1, you couldn’t even use subqueries.
SELECT @oldGroup := 0, @count := 0;
SELECT
@oldGroup := groupId,
theTable.*
FROM theTable
HAVING (@count := IF(groupId <=> @oldGroup, @count+1, 0)) < 5
ORDER BY groupId, rating;

Leave a Reply