sql >> Databasteknik >  >> RDS >> Mysql

Beställningsval baserat på anslutningsresultat (Sortera konversationer på senast skickat meddelande)

Problemet beror på en MySQL-specifik förlängning av beteendet hos GROUP BY klausul. Andra databaser skulle skapa ett fel... något som liknar on-aggregate i SELECT-listan". (Vi kan få MySQL att skicka ett liknande fel, om vi inkluderar ONLY_FULL_GROUP_BY i sql_mode.)

Problemet med uttrycket messages.created är som refererar till ett värde från en obestämd rad i GROUP BY. ORDER BY operationen inträffar mycket senare i behandlingen, efter GROUP BY operationen.

För att få det "senaste" skapat för varje grupp, använd ett aggregat uttryck MAX(messages.created) .

Att få de andra värdena från samma rad är lite mer komplicerat.

Förutsatt att created är unikt inom ett givet conversation_id grupp (eller, om det inte är garanterat att det inte är unikt, och du är okej med att returnera flera rader med samma värde för created ...

För att få den senaste created för varje conversation_id

SELECT lm.conversation_id
     , MAX(lm.created) AS created
  FROM conversation lc
  JOIN message lm
    ON lm.conversation_id = lc.id
 WHERE (lc.creator_id = :userId OR lc.to_id = :userId)
 GROUP BY lm.conversation_id

Du kan använda det som en inlinevy för att få hela raden med den senast created

SELECT c.*
     , m.*
  FROM ( SELECT lm.conversation_id
              , MAX(lm.created) AS created
           FROM conversation lc
           JOIN message lm
             ON lm.conversation_id = lc.id
          WHERE (lc.creator_id = :userId OR lc.to_id = :userId)
          GROUP BY lm.conversation_id
       ) l
  JOIN conversation c
    ON c.id = l.conversation_id
  JOIN messages m
    ON m.conversation_id = l.conversation_id
   AND m.created         = l.created
 WHERE (c.creator_id = :userId OR c.to_id = :userId)

ANMÄRKNINGAR:

Du kan lägga till en ORDER BY klausul för att beställa raderna som returneras hur du behöver.

WHERE klausulen på den yttre frågan är sannolikt överflödig och onödig.

Vi föredrar att undvika att använda SELECT * , och föredrar att uttryckligen lista de uttryck som ska returneras.




  1. Använda förberedda uttalanden med mysql i python

  2. Problem med int(11) datatype i MYSQL

  3. Hur man anger den invarianta kulturen när man använder FORMAT() i SQL Server

  4. SQL tidsskillnad inom en tabell