2011-01-23 8 views
8

Tengo algún tipo de solicitud imposible :).SQL - Dame 3 hits para cada tipo solo

Tengo una tabla donde una de las columnas se llama type. Me gustaría SELECCIONAR 3 registros para cada tipo en esa columna. ¿Es eso posible?

Tenga en cuenta también que estoy usando MySQL y Sphinx.

ACTUALIZACIÓN: Estructura de tabla

id  title  type 
1  AAAA   string1 
2  CCCC   string2 
3  EEEE   string2 
4  DDDD   string2 
5  FFFF   string2 
6  BBBB   string2 
6  BBBB   string2 

Lo que yo quiero que mi MySQL para volver es (hasta 3 registros para cada tipo ordenado por título):

id  title  type 
1  AAAA   string1 
6  BBBB   string2 
2  CCCC   string2 
4  DDDD   string2 
+3

Primero, casi nada es imposible. En segundo lugar, ¿por qué no mostrar la estructura de su tabla y lo que ha intentado hasta ahora? – ircmaxell

Respuesta

12
select id, title, type 
from (select id, title, type, 
       @num := if(@group = type, @num + 1, 1) as row_number, 
       @group := type as dummy 
     from your_table 
     order by type, title) as x 
where row_number <= 3 

(! Usos a different article en el mismo sitio que Martin Wickman's answer)

+0

¡Muy, muy bien! – xpepermint

+0

+1 para la orden fija por – RichardTheKiwi

0

Salida this artículo. Teniendo en cuenta:

+--------+------------+-------+ 
| type | variety | price | 
+--------+------------+-------+ 
| apple | gala  | 2.79 | 
| apple | fuji  | 0.24 | 
| apple | limbertwig | 2.87 | 
| orange | valencia | 3.59 | 
| orange | navel  | 9.36 | 
| pear | bradford | 6.05 | 
| pear | bartlett | 2.14 | 
| cherry | bing  | 2.55 | 
| cherry | chelan  | 6.33 | 
+--------+------------+-------+ 

Consulta:

select type, variety, price 
from fruits 
where (
    select count(*) from fruits as f 
    where f.type = fruits.type and f.price < fruits.price 
) <= 2; 
+0

Esta consulta mostrará vínculos, por lo que si 4 frutas tienen el mismo precio, todas se muestran (en lugar de 3). Tampoco ha habido ningún intento de vincular a la pregunta. – RichardTheKiwi

+0

Si seis variedades de manzanas compartieran el mismo precio más bajo, se devolverían las seis. Pero el ejemplo del PO estoy pensando que id es probablemente un identificador único (si, es decir, los dos "6" s se producen como resultado de un JOIN) y podría usar la columna de identificación en lugar de la columna de precios para obtener un resultado correcto garantizado. –

2

Cuando la tabla es grande y la recolección es más impredecible, la numeración de filas debe ordenarse por tipo en la consulta interna para que funcionen las variables de efecto lateral.

select id, title, type 
from (select id, title, type, 
     @r := CASE WHEN @g = type THEN @r+1 ELSE 1 END r, 
     @g := type 
     from tbl 
     order by type, title) as x 
where row_number <= 3 
# order by type, title 

Otra forma de hacer esto sin usar lado efectuar las variables, si no hay dos registros son exactamente los mismos en (título, tipo, id), es la siguiente. Esto usa solo SQL estándar ANSI SQL92. Sin embargo, puede ser más lento que el anterior.

select A.id, A.title, A.type 
from tbl A 
left join tbl B on 
    A.title = B.title and 
    (A.type < B.type or 
    (A.type = B.type and A.id < A.id)) 
group by A.id, A.title, A.type 
having count(B.title) <= 2 
+0

Sí, vi eso e hice esa solución antes de publicarla. –

2

Si usted tiene un índice en (type, title), y usted sabe los valores posibles para type, creo que SQL dinámico es el camino a seguir (por una vez) para un mejor rendimiento.

Para cada posible valor de type, agregue una unión all y seleccione para ese tipo específico. La consulta final se verá como la siguiente consulta:

(select * from t1 where type = 'string1' order by title limit 3) 
    union all 
(select * from t1 where type = 'string2' order by title limit 3) 
    union all 
(select * from t1 where type = 'string3' order by title limit 3); 

Se ejecuta en menos de 1 segundo en una mesa con 1.000.000 de filas, mientras que las otras soluciones (Martins & Cyberkiwis) lleva aproximadamente 11 segundos.

La diferencia se debe a que la consulta anterior puede obtener las tres primeras entradas de título para cada tipo y luego detener, mientras que la función de análisis simulado debe analizar toda la tabla.

+0

Mi base de datos tiene 200k registros y hay más de 500 tipos. ¿Que sugieres? – xpepermint

+0

@xpepermint, ve con la solución Martins. Solo sepa que se volverá más lento a medida que agrega registros. En algún momento, será más rápido realizar 500 consultas en un bucle. Dependiendo de su configuración, este puede ser el caso. Tienes que medirte a ti mismo. – Ronnis

Cuestiones relacionadas