2012-01-17 4 views
3

У меня есть такая таблица для простого чата:запроса возвращает дополнительные строки

messages table structure 
+----+---------+-----------+---------+------+------+ 
| id | to_user | from_user | message | read | sent | 
+----+---------+-----------+---------+------+------+ 

И мне нужно, чтобы получить список каждого разговора, который выглядит как то

Username ---- Message ---- Date 

Я использую этот запрос сделать это:

SELECT * 
FROM `messages` 
WHERE `sent` 
IN (
    SELECT MAX(`sent`) 
    FROM `messages` 
    WHERE `from_user` = '1' --id of user who is requesting the list 
    OR `to_user` = '1' --id of user who is requesting the list 
    GROUP BY `to_user` , `from_user` 
    ) 
LIMIT 0 , 30 

И это работает почти нормально, моя проблема в том, что она возвращает меня не последние сообщений этого разговора, но последнее сообщение от каждого пользователя, так скажем, пользователь 1 и 2 говорят и я получаю этот список, это то, что я получаю:

+----+---------+-----------+-----------------------+------+---------------------+ 
| id | to_user | from_user | message    | read | sent    | 
+----+---------+-----------+-----------------------+------+---------------------+ 
| 3 |  2 |   1 | Message 1 from user 1 | 0 | 2012-01-11 13:20:54 | 
| 4 |  1 |   2 | Message 1 from user 2 | 0 | 2012-01-11 13:24:59 | 
+----+---------+-----------+-----------------------+------+---------------------+ 

И я хотел бы получить только в прошлом сообщение , причина sent поле самое высокое в 4-й записи, так как я могу его решить?

EDIT После удаления group by я получаю только одно сообщение, даже если пользователь разговаривает с более чем одним пользователем

+0

См. Мой ответ за * правильный * ответ (а не тот, который вы приняли, что не так) – Bohemian

ответ

1

Вот как это сделать:

SELECT * 
FROM (SELECT * 
    FROM messages 
    WHERE from_user = ? 
    OR to_user = ? 
    ORDER by from_user, to_user, sent DESC 
) x 
GROUP BY from_user, to_user 
ORDER BY sent DESC 
LIMIT 1; 

В MySQL, группа по без агрегирования других столбцов возвращает первую строку для каждой группы. Выбрав форму упорядоченного набора строк (внутренний запрос), мы получаем последние строки для каждого разговора.

+0

актуально, это еще хуже, мне не нужно только последнее сообщение ... мне нужно получить последнее сообщение о каждом разговоре. – Linas

+0

@Linas Извините, неверно сформулировал вопрос. Попробуй это сейчас! – Bohemian

+0

это делает то же самое, что и мой текущий запрос, он получает от меня два последних сообщения из каждого разговора, и мне нужно найти способ получить только последний, и когда я думаю, что это действительно актуально, сделайте последнее сообщение каждого пользователя , поэтому мне нужно найти способ получить только от одного пользователя, его трудно объяснить ... – Linas

0

Удалите условие group by в вашем in заявление - это бесполезно в этом случае. Он возвращает sent временную метку для каждого отдельного сопряжения to_user и from_user. Вы действительно просто хотите max sent, где to_user или from_user равное определенное значение. Потеряйте group by, и вы вернете ровно одну запись с последним сообщением либо пользователю, либо пользователю.

Это выглядит следующим образом:

SELECT * 
FROM `messages` 
WHERE `sent` 
IN (
    SELECT MAX(`sent`) 
    FROM `messages` 
    WHERE `from_user` = '1' --id of user who is requesting the list 
    OR `to_user` = '1' --id of user who is requesting the list 
    ) 
LIMIT 0 , 30 
+0

-1 Это на самом деле не работает - оно вернет все сообщения, отправленные в то время, независимо от того, кто отправил/принял это – Bohemian

1
SELECT * 
FROM `messages` 
WHERE `sent` 
IN (
    SELECT MAX(`sent`) 
    FROM `messages` 
    WHERE (`from_user` = '1' OR `to_user` = '1') 
    ) 
LIMIT 0 , 30 

GroupBy собирается conbine их я верю.

1

Вы получаете последнее сообщение от каждого пользователя, потому что вы сделали GROUP BY для: to_user и from_user.

В запросе нет необходимости использовать предложение GROUP BY.

Смежные вопросы