Sto cercando di creare un elenco di messaggi, come Facebook.
- Mostra solo l'ultimo messaggio di una conversazione degli utenti (cronologia)
- quando invio mostra il mio, quando ricevo risposta mostra i messaggi con risposta (1 riga)
dati del database :
Query SQL
SELECT m.message_id, u.username, m.subject, m.message
, m.status, UNIX_TIMESTAMP(m.date) as date
FROM users u
LEFT JOIN messages m ON m.sender_id = u.id
WHERE m.message_id in (SELECT max(msg.message_id)
FROM messages msg
WHERE msg.receiver_id = 3
GROUP BY sender_id)
UNION
SELECT m.message_id, u.username, m.subject, m.message
, m.status, UNIX_TIMESTAMP(m.date) as date
FROM users u
LEFT JOIN messages m ON m.receiver_id = u.id
WHERE m.message_id in (SELECT max(msg.message_id)
FROM messages msg
WHERE msg.sender_id = 3
GROUP BY receiver_id)
GROUP BY u.username
ORDER BY date DESC
Provo a ricevere tutti i messaggi che invio (mio id = 3) e tutti quelli che mi sono stati inviati e raggruppati per nome utente
Risultato SQL:
Array
(
[0] => Array
(
[message_id] => 10
[username] => 8888
[subject] => без темы
[message] => 555
[status] => 0
[date] => 11 August 2012, 2:22
[user_image] => http://127.0.0.1/auth_system_1/upload_images/65_empty.jpg
)
[1] => Array
(
[message_id] => 7
[username] => 8888
[subject] => hi
[message] => 333
[status] => 0
[date] => 11 August 2012, 2:15
[user_image] => http://127.0.0.1/auth_system_1/upload_images/65_empty.jpg
)
[2] => Array
(
[message_id] => 4
[username] => 6666
[subject] => Тема
[message] => 2
[status] => 0
[date] => 11 August 2012, 2:02
[user_image] => http://127.0.0.1/auth_system_1/upload_images/65_empty.jpg
)
[3] => Array
(
[message_id] => 1
[username] => fffffffff
[subject] => privet
[message] => tttt
[status] => 0
[date] => 11 August 2012, 1:38
[user_image] => http://127.0.0.1/auth_system_1/upload_images/65_empty.jpg
)
)
Come potete vedere GROUP BY
il nome utente non funziona. Mostra 3-> 7 e 7-> 3 ma 7-> 3 era una risposta e l'ultimo messaggio. Non so perché il gruppo non funzioni. Forse puoi aiutarmi con un modo più semplice per risolvere questo problema?
Quindi, l'SQL deve avere "sender_id = 3", "receiver_id = 3" e dal risultato della mia tabella i dati devono essere
- message_id -> 1
- message_id -> 4
- message_id -> 10
risposte:
1 per risposta № 1Penso che la tua query stia producendo i risultati "giusti", come se ti piacerebbe vedere l'ultimo messaggio in alcune delle conversazioni, dovresti davvero raggruppare per conversation_id
. Tuttavia, non vedo questo campo nello schema.
Se fate WHERE sender_id = 3 GROUP BY receiver_id
, allora è corretto, quella query ti restituisce i messaggi 1 e 7, "perché quei messaggi erano stati inviati a diverso persone, quindi nel tuo progetto sono conversazioni diverse.
Se vuoi vedere solo l'ultimo messaggio inviato da te in generale, rimuovi GROUP BY
nella seconda parte del tuo UNION
. Altrimenti, considera la possibilità di riprogettare il tuo schema.
MODIFICARE:
Prova questa query:
SELECT m.message_id, u.username, m.subject, m.message,
m.status, UNIX_TIMESTAMP(m.date) as `date`
FROM users u
LEFT JOIN messages m ON m.sender_id = u.id
WHERE m.message_id IN (
SELECT max(message_id)
FROM messages
WHERE receiver_id = 3 OR sender_id = 3
GROUP BY least(sender_id,receiver_id),
greatest(sender_id,receiver_id)
);
Alcune note:
UNION
non è più necessario;- Questo approccio tratterà tutte le e-mail tra 2 parti come un'unica conversazione, il che non è sempre vero. Potresti voler riprogettare questo approccio;
- È un cattivo stile usare parole riservate (come
date
) per i nomi o gli alias delle colonne, cerca di evitarlo. Oppure usa i backtick se li usi.