2017-04-11 1 views
2

ich die Nachrichten-Tabelle wie folgt formatiert:Abfragen Gespräche von Nachrichten Tabelle

+------------------------------------------------------------------+ 
| id|sender_id| recipient_id | message_text |created_at   | 
+------------------------------------------------------------------+ 
| 1 | 2  | 10   | "test1"  |"2017-04-10 09:05:45" | 
| 2 | 10  | 2   | "test2"  |"2017-04-10 09:05:47" | 
| 3 | 2  | 4   | "test3"  |"2017-04-10 09:05:49" | 
| 4 | 10  | 4   | "test4"  |"2017-04-10 09:05:51" | 
| 5 | 4  | 2   | "test5"  |"2017-04-10 09:05:53" | 
| 6 | 2  | 10   | "test6"  |"2017-04-10 09:05:58" | 
+------------------------------------------------------------------+ 

Was ich versuche ein alle „Gespräche“ des Benutzers (zB Benutzer mit id 2) angemeldet zu tun ist, erhalten zusammen mit den letzten Nachrichten für diese Konversation. konnte ich die IDs der Benutzer user2 ziehen hat Meldungen bei der Verwendung dieser Abfrage:

select distinct users.id 
from messages, users where 
(recipient_id = 2 and users.id = sender_id) 
or 
(sender_id = 2 and users.id = recipient_id); 

Was ergibt dies ist

4 
10 

als benutzer2 entweder Nachrichten von diesen beiden Personen gesendet und/oder empfangen hat (test1, test2, test6 für 10 und test3, test5 für 4).

Was kann ich nicht tun, ist diese Abfrage ändern, so dass es auch die letzte Nachricht gesendet oder empfangen werden durch die erbrachte id liefert - zum Beispiel

4 | test5 
10 | test6 

Antwort

3

Wenn ich Ihre Anforderung richtig verstanden habe, möchten Sie das letzte Nachrichtendatum für jede Konversation erhalten, die einen bestimmten Benutzer betrifft. In diesem Fall können wir über Konversationen für einen bestimmten Benutzer aggregieren und das letzte Nachrichtendatum beibehalten.

SELECT m1.* 
FROM messages m1 
INNER JOIN 
(
    SELECT LEAST(sender_id, recipient_id) AS first, 
      GREATEST(sender_id, recipient_id) AS second, 
      MAX(created_at) AS recent_date 
    FROM messages 
    WHERE sender_id = 2 OR recipient_id = 2 
    GROUP BY LEAST(sender_id, recipient_id), 
      GREATEST(sender_id, recipient_id) 
) m2 
    ON LEAST(m1.sender_id, m1.recipient_id) = m2.first AND 
     GREATEST(m1.sender_id, m1.recipient_id) = m2.second AND 
     m1.created_at = m2.recent_date 

Ausgang:

enter image description here

Erläuterung:

Die Herausforderung in dieser Abfrage ist eine Möglichkeit, Gruppengespräche zwischen zwei Benutzern gemeinsam zu finden. Ich habe den LEAST/GREATEST Trick verwendet, der eine Art ist, dass wir eine und 4 -> 2 Konversation als logisch dasselbe behandeln können. Dann können wir unter Verwendung von GROUP BY das letzte Konversationsdatum für dieses Paar von Konversationsbenutzern identifizieren. Die Unterabfrage in meiner obigen Antwort findet also für jedes Benutzerpaar ohne Rücksicht auf irgendeine Reihenfolge das Paar zusammen mit dem letzten Konversationsdatum. Wir verbinden dann dieses Ergebnis zurück zu der messages Tabelle, um den tatsächlichen spätesten Mitteilungstext einzubringen.

Demo hier:

Rextester

+0

Das gibt mir tatsächlich fast das Ergebnis, das ich brauche, aber ich brauche die Nachrichten der letzten Nachrichten statt ihrer Daten.Wenn ich nur Nachrichtentext hinzufüge, um auszuwählen, ist der Teil, den Sie mit Daten gemacht haben, immer noch korrekt, aber Nachrichten, die ich bekomme, stimmen nicht mit den Daten überein. Ich mag den Ansatz. Könnten Sie mir auch erklären, wie Sie zu dieser Lösung gekommen sind? – hpdobrica

+0

die modifizierte Abfrage funktioniert wie ein Charme! Ich würde wirklich gerne ein bisschen darüber hören, was du dort gemacht hast, ich will es nicht einfach kopieren/einfügen haha ​​:) – hpdobrica

+0

@hpdobrica Ich gab dir eine tiefere Erklärung. –

0

Verwenden Sie eine order_by created_at desc Erklärung am Ende der Anfrage zu Erhalte die neuesten Nachrichten.

+1

Dies wird nicht das gewünschte Ergebnis geben, da Ihr Ansatz uns mit nur einem Datensatz verlassen würde. –

+0

'deutliche users.id wählen, messages.message_text von Nachrichten, die Benutzer (recipient_id = 2 und users.id = SENDER_ID) oder (SENDER_ID = 2 und users.id = recipient_id) Sortieren nach messages.created_at desc ; ' das gibt mir alle Nachrichten zu/von Benutzer 2 geordnet von neu nach alt. Auch wenn ich Message_text zur Auswahl hinzufüge, bekomme ich nicht mehr nur 2 Datensätze, sondern alle Nachrichten, das ist auch der Teil des Problems. – hpdobrica

Verwandte Themen