获取组[MySQL]内表中前n个计数行

获取组[MySQL]内表中前n个计数行,mysql,sql,group-by,greatest-n-per-group,Mysql,Sql,Group By,Greatest N Per Group,我正在尝试将前三名的销售产品按类别分组,按交易发生次数排列前三名的产品id countid按每个类别排列。我一直在寻找可能的解决办法,但没有结果。在MySQL中看起来有点棘手,因为不能简单地使用top函数等等。下面是示例数据结构: +--------+------------+-----------+ | id |category_id | product_id| +--------+------------+-----------+ | 1 | 10 | 32

我正在尝试将前三名的销售产品按类别分组,按交易发生次数排列前三名的产品id countid按每个类别排列。我一直在寻找可能的解决办法,但没有结果。在MySQL中看起来有点棘手,因为不能简单地使用top函数等等。下面是示例数据结构:

+--------+------------+-----------+
|     id |category_id | product_id|
+--------+------------+-----------+
| 1      | 10         | 32        |
| 2      | 10         | 34        |
| 3      | 10         | 32        |
| 4      | 10         | 21        |
| 5      | 10         | 100       |
| 6      | 7          | 101       |
| 7      | 7          | 39        |
| 8      | 7          | 41        |
| 9      | 7          | 39        |
+--------+------------+-----------+

如果您运行的是MySQL 8.0,您可以使用窗口函数rank来实现以下功能:

select *
from (
    select 
        category_id,
        product_id,
        count(*) cnt,
        rank() over(partition by category_id order by count(*) desc) rn
    from mytable
    group by category_id, product_id
) t
where rn <= 3

如果您运行的是MySQL 8.0,您可以使用窗口函数rank来实现以下功能:

select *
from (
    select 
        category_id,
        product_id,
        count(*) cnt,
        rank() over(partition by category_id order by count(*) desc) rn
    from mytable
    group by category_id, product_id
) t
where rn <= 3

在MySQL的早期版本中,我建议使用变量:

select cp.*
from (select cp.*,
             (@rn := if(@c = category_id, @rn + 1,
                        if(@c := category_id, 1, 1)
                       )
             ) as rn
      from (select category_id, product_id, count(*) as cnt
            from mytable
            group by category_id, product_id
            order by category_id, count(*) desc
           ) cp cross join
           (select @c := -1, @rn := 0) params
     ) cp
where rn <= 3;

在MySQL的早期版本中,我建议使用变量:

select cp.*
from (select cp.*,
             (@rn := if(@c = category_id, @rn + 1,
                        if(@c := category_id, 1, 1)
                       )
             ) as rn
      from (select category_id, product_id, count(*) as cnt
            from mytable
            group by category_id, product_id
            order by category_id, count(*) desc
           ) cp cross join
           (select @c := -1, @rn := 0) params
     ) cp
where rn <= 3;

不幸的是,函数秩不存在,所以我需要找到一些workaround@kpl92:我用早期版本的解决方案更新了我的答案。是的,但我不知道为什么我没有得到任何结果。不幸的是,函数秩不存在,所以我需要找到一些workaround@kpl92:我用早期版本的解决方案更新了答案。是,但是我不知道为什么我没有得到结果是的,你的查询在我的MySQL版本中运行得很好。谢谢!是的,您的查询与我的MySQL版本配合得很好。谢谢!