¿Cómo obtener el último registro en cada grupo usando GROUP BY?


Digamos que tengo una tabla llamada messages con las columnas:

id | from_id | to_id | subject | message | timestamp

Quiero recibir el último mensaje solo de cada usuario, como verías en tu bandeja de entrada de FaceBook antes de profundizar en el hilo real.

Esta consulta parece acercarme al resultado que necesito:

SELECT * FROM messages GROUP BY from_id

Sin embargo, la consulta me está dando el mensaje más antiguo de cada usuario y no el más reciente.

No puedo entender esto.

Author: Jonathan Leffler, 2012-06-12

6 answers

Debe encontrar los últimos valores timestamp en cada grupo (subconsulta) y luego unir esta subconsulta a la tabla -

SELECT t1.* FROM messages t1
  JOIN (SELECT from_id, MAX(timestamp) timestamp FROM messages GROUP BY from_id) t2
    ON t1.from_id = t2.from_id AND t1.timestamp = t2.timestamp;
 77
Author: Devart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-12 15:18:47

Prueba esto

SELECT * FROM messages where id in (SELECT max(id) FROM messages GROUP BY from_id ) order by id desc
 13
Author: Venu M,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-21 18:40:48

Esta consulta devuelve el último registro para cada Form_id:

    SELECT m1.*
     FROM messages m1 LEFT JOIN messages m2
     ON (m1.Form_id = m2.Form_id AND m1.id < m2.id)
     WHERE m2.id IS NULL;
 2
Author: leyla azari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-10 07:22:38

Este es un problema estándar.

Tenga en cuenta que MySQL le permite omitir columnas de la cláusula GROUP BY, lo que SQL estándar no hace, pero no obtiene resultados deterministas en general cuando utiliza la facilidad MySQL.

SELECT *
  FROM Messages AS M
  JOIN (SELECT To_ID, From_ID, MAX(TimeStamp) AS Most_Recent
          FROM Messages
         WHERE To_ID = 12345678
         GROUP BY From_ID
       ) AS R
    ON R.To_ID = M.To_ID AND R.From_ID = M.From_ID AND R.Most_Recent = M.TimeStamp
 WHERE M.To_ID = 12345678

He añadido un filtro en el To_ID para que coincida con lo que es probable que tenga. La consulta funcionará sin ella, pero devolverá muchos más datos en general. No es necesario indicar la condición tanto en la consulta anidada como en la consulta externa (el optimizador debe empujar la condición hacia abajo automáticamente), pero no puede hacer ningún daño para repetir la condición como se muestra.

 1
Author: Jonathan Leffler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-12 15:18:57

Simplemente complementando lo que dijo Devart, el siguiente código no está ordenando de acuerdo con la pregunta:

SELECT t1.* FROM messages t1
  JOIN (SELECT from_id, MAX(timestamp) timestamp FROM messages GROUP BY from_id) t2
    ON t1.from_id = t2.from_id AND t1.timestamp = t2.timestamp;

La cláusula "GROUP BY" debe estar en la consulta principal ya que primero necesitamos reordenar el "SOURCE" para obtener el "grouping" necesario así que:

SELECT t1.* FROM messages t1
  JOIN (SELECT from_id, MAX(timestamp) timestamp FROM messages ORDER BY timestamp DESC) t2
    ON t1.from_id = t2.from_id AND t1.timestamp = t2.timestamp GROUP BY t2.timestamp;

Saludos,

 1
Author: Bruno de Oliveira,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-15 13:53:42

Tienes que pedirlos.

SELECT * FROM messages GROUP BY from_id ORDER BY timestamp DESC LIMIT 1

 -4
Author: Marcus Recck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-12 15:12:14