Próbuję utworzyć listę wiadomości, na przykład Facebook.
- Pokazywanie tylko ostatniej wiadomości z rozmowy użytkownika (historia)
- kiedy wysyłam pokaż moje, kiedy dostaję odpowiedź pokaż odebrane wiadomości (1 rząd)
dane bazy danych :
Zapytanie 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
Próbuję odbierać wszystkie wiadomości, które wysyłam (mój identyfikator = 3) oraz wszystkie wiadomości wysłane do mnie i pogrupowane według nazwy użytkownika
Wynik 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
)
)
Jak widzisz GROUP BY
nazwa użytkownika nie działa. Pokazuje 3-> 7 i 7-> 3, ale 7-> 3 była odpowiedzią i ostatnią wiadomością. Nie wiem, dlaczego grupa nie działa. Może pomożesz mi z łatwiejszym sposobem rozwiązania tego problemu?
Tak więc, SQL musi mieć „sender_id = 3”, „reader_id = 3”, a wynik z mojej tabeli musi wynosić
- message_id -> 1
- message_id -> 4
- message_id -> 10
Odpowiedzi:
1 dla odpowiedzi № 1Myślę, że twoje zapytanie daje „właściwe” wyniki, tak jakbyś „chciał zobaczyć ostatnią wiadomość w niektórych rozmowach, powinieneś naprawdę pogrupować według conversation_id
. Nie widzę tego pola w schemacie.
Jeśli zrobisz WHERE sender_id = 3 GROUP BY receiver_id
, to prawda, że zapytanie zwraca ci wiadomości 1 i 7, „ponieważ te wiadomości zostały wysłane różne ludzie, dlatego w twoim projekcie są to różne rozmowy.
Jeśli chcesz zobaczyć tylko ostatnią wysłaną przez Ciebie wiadomość, po prostu ją usuń GROUP BY
w drugiej części twojego UNION
. W przeciwnym razie rozważ ponowne zaprojektowanie schematu.
EDYTOWAĆ:
Wypróbuj to zapytanie:
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)
);
Niektóre uwagi:
UNION
nie jest już potrzebny;- Takie podejście potraktuje wszystkie wiadomości e-mail między dwiema stronami jako pojedynczą rozmowę, co nie zawsze jest prawdą. Być może zechcesz przeprojektować to podejście;
- Używanie słów zastrzeżonych (np
date
) w przypadku nazw lub aliasów kolumn, staraj się tego unikać. Lub użyj odwrotnych znaków, jeśli ich używasz.