¿Cuál es la mejor manera de seleccionar los dos primeros loggings de cada grupo con un command "SELECCIONAR"?

Por ejemplo, tengo la siguiente tabla:

id group data 1 1 aaa 2 1 aaa 3 2 aaa 4 2 aaa 5 2 aaa 6 3 aaa 7 3 aaa 8 3 aaa 

¿Cuál es la mejor manera de seleccionar los dos primeros loggings de cada grupo con un command "SELECCIONAR"? Si no hay una buena manera de hacerlo, ¿qué rutina sugieres? (En PHP)

(resultado model)

 1 1 aaa 2 1 aaa 3 2 aaa 4 2 aaa 6 3 aaa 7 3 aaa 

Sabía que la unión cruzada por a.id> = b.id en una subconsulta puede estar funcionando, pero estoy buscando una solución más escalable que se pueda aplicar en una tabla con millones de loggings. Gracias

 select a.* from Tablename a where ( select count(*) from Tablename as b where a.group = b.group and a.id >= b.id ) <= 2 
  • Demostración de SQLFiddle

Me gusta este truco, que hace uso de la function agregada GROUP_CONCAT y FIND_IN_SET:

 SELECT Tablename.* FROM Tablename INNER JOIN ( SELECT `group`, GROUP_CONCAT(id ORDER BY id) ids FROM Tablename GROUP BY `group`) grp ON Tablename.`group` = grp.`group` AND FIND_IN_SET(Tablename.id, ids)<=2 ORDER BY Tablename.`group`, Tablename.id 

Las actuaciones no pueden ser demasiado buenas, ya que no puede hacer uso de un índice.

O también puedes usar esto:

 SELECT t1.id, t1.`group`, t1.data from Tablename t1 INNER JOIN Tablename t2 ON t1.`group` = t2.`group` AND t1.id>=t2.id GROUP BY t1.id, t1.`group`, t1.data HAVING COUNT(*)<=2 ORDER BY t1.`group`, t1.id, t1.data 

Selecciona, filtra y ordera su consulta como normal y luego

para MSSQL

 SELECT TOP 2 * FROM foo; 

De lo que puedo recordar es que Sybase , Oracle y algunos otros RDBMS usan esta syntax.

para MySQL lo haces

 SELECT * FROM foo LIMIT 2; 

Actualizar:

Sí, leí mal tu pregunta, lo siento. Parece que algunos de nosotros lo hicimos 🙂

Luego depende de si RDBMS admite HAVING o no, etc. Puede build una consulta usando HAVING o usando IN y una subconsulta en la cláusula IN .

Para MSSQL creo que podrías hacer algo como (código no probado)

 SELECT id, data FROM ( SELECT id, data, Rank() over (Partition BY group ORDER BY id DESC ) AS Rank FROM table ) rs WHERE Rank <= 2) 

Pero como esto depende de su RDBMS, le pido que mire las preguntas similares y vea cuál funciona mejor para su caso, ya que MSSQL admite algunas cosas que MySQL no tiene y al revés.

Aquí hay unos ejemplos

Seleccione los 10 loggings principales para cada categoría

Cómo seleccionar los dos últimos loggings para cada topic_id en MySQL