2010-04-07 42 views
9

Tengo que seleccionar los dos últimos registros para cada tema.Cómo seleccionar los dos últimos registros para cada topic_id en MySQL

ejemplo: tabla: msg

id | topic_id 
------------ 
1 | 1 
2 | 1 
3 | 1 
4 | 1 
5 | 2 
6 | 2 
7 | 2 
8 | 3 
9 | 3 
10 | 3 

Quiero obtener estas filas:

3 1 
4 1 
6 2 
7 2 
9 3 
10 3 

¿Cómo puedo hacer esto?

gracias

+0

¿hay atajos que podamos suponer? por ejemplo, en los datos anteriores, los ID están ascendiendo sin agujeros y para los ID ascendentes también tiene un topic_id ascendente, si podemos suponer que facilitará la consulta. otro enfoque podría usar la suposición de que hay al menos dos entradas para cada topic_id. podemos suponer eso? – Unreason

Respuesta

1

Usted podría

SELECT a.id, a.topic_id 
FROM MSG a 
WHERE a.id IN (
    SELECT t.id 
    FROM MSG t 
    WHERE a.topic_id = t.topic_id 
    ORDER BY t.id DESC 
    LIMIT 2) 
ORDER BY a.topic_id, a.id 

EDIT: Como parece que MySQL no permite (! Sin embargo, que va a ser posible en futuras versiones) para limitar el uso de subconsultas aquí es una solución generalizada (sin supuestos de acceso directo, excepto que msg.id es único por topic_id):

SELECT a.id, a.topic_id 
FROM MSG a 
WHERE a.id IN (
    SELECT MAX(t.id) 
    FROM MSG t 
    WHERE a.topic_id = t.topic_id 
      ) OR 
     a.id IN (
    SELECT MAX(t.id) 
    FROM MSG t 
    WHERE a.topic_id = t.topic_id AND 
    t.id NOT IN (
     SELECT MAX(t2.id) 
     FROM MSG t2 
     WHERE t.topic_id = t2.topic_id 
       ) 
      )  
ORDER BY a.topic_id, a.id 

por supuesto esto no es agradable, pero no es usted. Si se puede suponer que los id en topic_id son ascendentes sin agujeros, se pueden realizar mejoras adicionales a la consulta.

+0

me da el siguiente error "MySQL aún no es compatible con 'LIMIT & IN/ALL/ANY/ALGUNA subconsulta'" – Salil

+0

respuesta actualizada para compensar la limitación de mysql de la que no tenía conocimiento. – Unreason

0

Me gustaría saber una mejor respuesta para esto, pero la siguiente consulta funcionará.

SELECT * FROM msg where id in (SELECT m.id FROM msg m group by topic_id) 
      or id in (SELECT m1.id FROM msg m1 where id not in (SELECT m2.id FROM msg m2 roup by topic_id) 
group by topic_id) order by id 
+0

en realidad no (hay un error que falta g en la segunda subconsulta, busca el rup) pero lo más importante: mysql no garantiza que el valor de las columnas no incluidas en el grupo provenga del último registro y puede devolver cualquier valor que elija (o en otras palabras, si su consulta arroja los resultados deseados, entonces, por definición, es solo por coincidencia y podría dejar de funcionar en cualquier momento) – Unreason

3

Un trabajo alrededor de SQL que no admite el límite seguido de la cláusula IN es simple. Simplemente crea otra subconsulta dentro de tu cláusula IN. Así por ejemplo.

SELECT a.id, a.topic_id 
FROM MSG a 
WHERE a.id IN (
    SELECT t.id 
    FROM (Select * from MSG t 
    WHERE a.topic_id = t.topic_id 
    ORDER BY t.id DESC 
    LIMIT 2)alias) 
ORDER BY a.topic_id, a.id 

Dejarme saber cómo funciona eso para usted.

+0

Con esta consulta, aparece el error "Columna desconocida" a.topic_id 'en' dónde cláusula'" – rayne

3
SELECT max(id), max(topic_id) FROM msg 
GROUP BY topic_id 

UNION 

SELECT max(id), max(topic_id) FROM msg 
WHERE id not in (
    SELECT max(id) as id FROM msg 
    GROUP BY topic_id) 
GROUP BY topic_id 
Cuestiones relacionadas