求助一个关于 group by 的问题

想要用group by实现每个分组限定条数,并且每个组都有顺序

具体例子见下面这个示例表吧,我想按照category来分组,每个组限制2条数据,每个分组按照weight降序排

id weight category
1 100 1
2 90 1
3 110 1
4 40 2
5 60 4
6 90 4

也就是说查询结果应该要类似:

id weight category
3 110 1
1 100 1
4 40 2

有什么好办法吗?

xcaptain
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 2
xcaptain

整体的思路是:

  1. 把表分区,使得每个分区都有一个连续自增的排序字段

    对应的sql见下:

    SELECT 
    a.id, a.weight, a.category, COUNT(b.weight) + 1 AS rank
    FROM
    test_category a
        LEFT JOIN
    test_category b ON a.weight > b.weight
        AND a.category = b.category
    GROUP BY a.id , a.weight , a.category
    ORDER BY a.weight;

    查询结果如下:

    | id | weight | category | rank |
    |--- |------- |--------  |----- |
    | 4  | 40     | 2        | 1    |
    | 5  | 60     | 4        | 1    |
    | 6  | 90     | 4        | 2    |
    | 2  | 90     | 1        | 1    |
    | 1  | 100    | 1        | 2    |
    | 3  | 110    | 1        | 3    |
  2. 通过限制每个分区的条数,获得目标结果

    sql见下

    SELECT 
    *
    FROM
    (SELECT 
        a.id, a.weight, a.category, COUNT(b.weight) + 1 AS rank
    FROM
        test_category a
    LEFT JOIN test_category b ON a.weight > b.weight
        AND a.category = b.category
    GROUP BY a.id , a.weight , a.category
    ORDER BY a.weight) AS b
    WHERE
    b.rank <= 2
    ORDER BY category ASC , weight ASC;

    b.rank<=2的意思是只去排名前2的数据,也就限制了每个分区大小为2.

6年前 评论
xcaptain

组内排序的方法参考了 https://stackoverflow.com/questions/333366...

6年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!