Comment obtenir le dernier enregistrement dans chaque groupe en utilisant GROUP BY?

disons que j'ai une table appelée messages avec les colonnes:

id | from_id | to_id | subject | message | timestamp

je veux obtenir le dernier message de chaque utilisateur seulement, comme vous verriez dans votre boîte de réception FaceBook avant de creuser dans le fil réel.

Cette requête semble me proche du résultat j'ai besoin:

SELECT * FROM messages GROUP BY from_id

Toutefois, la requête me donne le message le plus ancien de chaque utilisateur et pas le plus récent.

Je n'arrive pas à comprendre celui-ci.

34
demandé sur Jonathan Leffler 2012-06-12 19:10:04

6 réponses

Vous devriez trouver la dernière timestamp valeurs dans chaque groupe (subquery), et puis joindre cette sousquery à la table -

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
répondu Devart 2012-06-12 15:18:47

Essayez ceci

SELECT * FROM messages where id in (SELECT max(id) FROM messages GROUP BY from_id ) order by id desc
13
répondu Venu M 2016-04-21 18:40:48

cette requête renvoie le dernier enregistrement pour chaque 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
répondu leyla azari 2017-08-10 07:22:38

C'est un problème standard.

notez que MySQL vous permet d'omettre les colonnes du groupe par clause, ce que le SQL Standard ne fait pas, mais vous n'obtenez pas de résultats déterministes en général lorsque vous utilisez la facilité 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

j'ai ajouté un filtre sur l' To_ID correspond à ce que vous êtes susceptible d'avoir. La requête fonctionnera sans elle, mais retournera beaucoup plus de données en général. L'état ne devrait pas besoin d'être indiqués dans la requête imbriquée et l'extérieur requête (l'optimiseur doit pousser la condition automatique), mais il ne peut pas faire de mal de répéter l'état comme indiqué.

1
répondu Jonathan Leffler 2012-06-12 15:18:57

juste en complément de ce Qu'a dit Devart, le code ci-dessous n'est pas en ordre selon la question:

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 clause "GROUP BY" doit être dans la requête principale car il faut d'abord réordonner le "SOURCE" pour obtenir le "grouping" nécessaire ainsi:

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;

Cordialement,

1
répondu Bruno de Oliveira 2015-09-15 13:53:42

vous devez les commander.

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

-4
répondu Marcus Recck 2012-06-12 15:12:14