MySQL Группируется по верхнему N числу каждого вида

StackOverflow https://stackoverflow.com/questions/1537606

  •  20-09-2019
  •  | 
  •  

Вопрос

У меня есть такой стол, как этот:

Rank      Letter
1         A
2         A
3         B
4         A
5         C
6         A
7         C
8         C
9         B
10        C 

И мне нужны 2 верхних строчки каждой буквы, упорядоченные по возрастанию ранга:

Rank      Letter
1         A
2         A
3         B
5         C
7         C
9         B

Как бы я это сделал?Довольно просто получить только топ-1, используя GROUP BY, но, похоже, я не могу заставить его работать для нескольких записей

Это было полезно?

Решение

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

Другие советы

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 что более эффективно.

Смотрите эту статью в моем блоге:

для получения более подробной информации об этом.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top