Reputation: 292
Please I am having a problem querying for the Top N per category from a data set resembling the one shown below. I have see various thread on this but I am having problem adapting their query to my specific problem.
+----+---------------------------------+-------+
| ID | Prod |Cat Id |
+----+---------------------------------+-------+
| 1 | kntrn | 1 |
| 2 | kntrn e | 1 |
| 3 | e spl | 1 |
| 4 | spl php | 1 |
| 5 | php cicarredgtal | 1 |
| 6 | cicarredgtal servecounterstrike | 1 |
| 7 | servecounterstrike com | 1 |
| 8 | zlv | 2 |
| 9 | zlv enter | 2 |
| 10 | spl php | 2 |
+----+---------------------------------+-------+
I want to group based on this rule (1) Select Top 3 Prod for each catid.
Please do note that top in this sense is the one highest count of prod in all category.
So for the example above spl php is the highest for catID 1 because it occurs twice across all category.
Upvotes: 0
Views: 1151
Reputation: 3537
This may not be very pretty, but I think it'll work:
SELECT cat_id, prod, pos FROM (
SELECT cat_id, pos, prod, if(@last_id = cat_id, @cnt := @cnt + 1, (@cnt := 0 || @last_id := cat_id)) cnt
FROM (
SELECT p.cat_id, pseq.cnt pos, pseq.prod
FROM (
SELECT prod, count(*) cnt FROM prods GROUP BY prod ORDER BY cnt DESC
) pseq
INNER JOIN prods p ON p.prod = pseq.prod
ORDER BY cat_id, pseq.cnt DESC
) po
) plist
WHERE cnt <= 3;
Based on the above data, this will return:
+--------+-----------+-----+
| cat_id | prod | pos |
+--------+-----------+-----+
| 1 | spl php | 2 |
| 1 | kntrn | 1 |
| 1 | kntrn e | 1 |
| 2 | spl php | 2 |
| 2 | zlv | 1 |
| 2 | zlv enter | 1 |
+--------+-----------+-----+
Upvotes: 1