2009-10-08 7 views
7

Tengo una tabla como la siguiente:MySQL Grupo A con el número N superior de cada especie

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

y necesito la 2 parte superior de cada letra ordenados por orden ascendente rango:

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

Cómo sería ¿Lo hago? Es bastante sencillo para obtener sólo el 1 por el uso de GROUP BY, pero me parece que no puede conseguir que funcione para múltiples entradas

Respuesta

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 

EDIT: (mi primer intento no funciona en MySQL (Quassnoi comentario), he modificado para que funcione en el servidor SQL, por ejemplo)

segundo intento:

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 
+0

'IN' predicado no funciona con' LIMIT' en 'MySQL' – Quassnoi

+0

lo siento, trabajo más con el servidor sql. Ahora tengo que encontrar otra solución para mysql y diferente de la tuya;) – manji

7
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 
       ) 

Es necesario tener un índice compuesto en (Letter, Rank) (en este orden)

Nota

esta construcción:

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

en lugar de mera md.Letter = mo.Letter

obliga Range checked for each record que es más ef ficiente.

Lee este artículo en mi blog:

para más detalles sobre esto.

+0

I' m obteniendo un error de "# 1242 - Subconsulta devuelve más de 1 fila" debido al LÍMITE 2 en la última subconsulta, ¿sabe por qué podría ser así? – Rik

+0

'LIMIT' incorrecto, reparado. – Quassnoi

+0

Esta es una respuesta antigua, pero la encontré útil. Sin embargo, encontré que no funciona como se esperaba. Si hay menos de 2 instancias de una letra, p. Ej., No devolverá ninguna de ellas. Puede agregar algo como esto: O ( SELECT COUNT (*) FROM mytable mi DONDE mi.letter = mo.letter ) <= 2) ; –

Cuestiones relacionadas