【问题标题】:MySQL Group By with top N number of each kindMySQL Group By,每种类型的前 N ​​个数
【发布时间】:2010-12-04 23:43:18
【问题描述】:

我有一张这样的桌子:

等级信 1个 2个 3乙 4个 5℃ 6个 7℃ 8℃ 9乙 10℃

我需要每个字母的前 2 个按升序排列:

等级信 1个 2个 3乙 5℃ 7℃ 9乙

我该怎么做?使用 GROUP BY 获得前 1 名相当简单,但我似乎无法让它适用于多个条目

【问题讨论】:

    标签: mysql group-by ranking


    【解决方案1】:
    SELECT  mo.Letter, md.Rank
    FROM    (
            SELECT  DISTINCT letter
            FROM    mytable
            ) mo
    JOIN    mytable md
    ON      md.Letter >= mo.Letter
            AND md.Letter <= mo.Letter
            AND Rank <=
            COALESCE
                    (
                    (
                    SELECT  Rank
                    FROM    mytable mi
                    WHERE   mi.letter = mo.letter
                    ORDER BY
                            Rank
                    LIMIT 1, 1
                    ),
                    0xFFFFFFFF
                    )
    

    您需要在(Letter, Rank) 上有一个复合索引(按此顺序)

    注意这个结构:

    md.Letter >= mo.Letter
    AND md.Letter <= mo.Letter
    

    而不仅仅是md.Letter = mo.Letter

    它强制Range checked for each record 更有效。

    在我的博客中查看这篇文章:

    了解更多详情。

    【讨论】:

    • 由于最后一个子查询的 LIMIT 2,我收到“#1242 - 子查询返回超过 1 行”的错误,你知道为什么会这样吗?
    • 这是一个旧答案,但我发现它很有用。然而,我确实发现它并没有按预期工作。如果一个字母的实例少于 2 个,例如,它不会返回任何一个。您可以添加如下内容: OR ( SELECT COUNT(*) FROM mytable mi WHERE mi.letter = mo.letter )
    • @Quassnoi 非常好——我比我更喜欢你的版本,谢谢 :)
    【解决方案2】:
    select distinct rank, letter
      from table1 t2
     where rank in 
             (select top 2 rank
                from table1 t2 
               where t2.letter = t1.letter 
               order by rank)
           order by letter, rank
    

    编辑:(我的第一次尝试在 MySql 上不起作用(Quassnoi 评论),我修改它以在 sql server 上工作)

    第二次尝试:

    select t.letter, t.rank
    from table1 t
    join (
        select t1.letter, min(t1.rank) m
        from table1 t1
        join (select t0.letter, min(t0.rank) m, count(1) c 
               from table1 t0 group by t0.letter) t2
        on t1.letter = t2.letter and ((t2.c = 1) or (t2.c > 1 and t1.rank > m))
        group by t1.letter) t3 
      on t.letter = t3.letter and t.rank <= t3.m
    

    【讨论】:

    • 对不起,我更多地使用 sql server。现在我必须为 mysql 找到另一个与你不同的解决方案;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-02
    • 1970-01-01
    • 2016-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多