Запрос на выбор 10 последних отправленных / полученных сообщений от / пользователей - PullRequest
0 голосов
/ 29 апреля 2010

Я хочу выбрать 10 последних сообщений, которые вы получили ИЛИ вы отправили различным пользователям.

Например, результаты должны отображаться так:

1. John1 - last message received 04/17/10 3:12 
2. Thomy - last message sent 04/16/10 1:26 
3. Pamela - last message received 04/12/10 3:51 
4. Freddy - last message received 03/28/10 9:00 
5. Jack - last message sent 03/20/10 4:53 
6. Tom - last message received 02/01/10 7:41 
..... 

Таблица выглядит так:

CREATE TABLE `messages` ( 
`id` int(11) NOT NULL AUTO_INCREMENT, 
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
`sender` int(11) DEFAULT NULL, 
`receiver` int(11) DEFAULT NULL, 
`content` text 
) 

Я думаю, что Facebook (и iPhone) использует это решение. Когда вы заходите в свой почтовый ящик, у вас есть последние полученные / отправленные сообщения, сгруппированные по пользователям (друзьям).

Так что я возьму пример. Если у меня есть тезисы (ОНИ ЗАКАЗЫВАЮТ):

**Mike**
**Tom**
**Pam**
Mike
Mike
**John**
John
Pam
**Steve**
**Bobby**
Steve
Steve
Bobby

Только сообщение с **** должно быть возвращено, потому что это последние сообщения, которые я отправил / получил от пользователя.

На самом деле я хочу последнее сообщение КАЖДОГО обсуждения.

Какое решение?

Ответы [ 4 ]

3 голосов
/ 29 апреля 2010

Вопрос несколько неясен. Если вы просто хотите, чтобы последние 10 сообщений были связаны с пользователем # 12345, просто используйте:

SELECT   *
FROM     messages
WHERE    sender = 12345 OR receiver = 12345
ORDER BY time DESC
LIMIT    10

Обновление в соответствии с вашими обновленными требованиями. Не самый элегантный, но работает до тех пор, пока ни один пользователь не отправляет два сообщения в одну секунду.

SELECT   m1.*
FROM     messages m1
         INNER JOIN (SELECT   MAX(time) AS time,
                              IF(receiver = 12345, sender, receiver ) AS user
                     FROM     messages
                     GROUP BY user) m2
           ON m1.time = m2.time AND (m1.sender = m2.user OR m1.receiver = m2.user)
WHERE    sender = 12345 OR receiver = 12345
ORDER BY m1.time DESC
1 голос
/ 03 апреля 2012

Запрос Макса Шавабке действительно помог мне понять эту проблему. При реализации этого на сайте, который я разрабатываю, я обнаружил крайнее условие, которое оно пропустило.

Существуют три возможных состояния для каждой цепочки сообщений:

  1. Вы отправляли сообщения туда и обратно.
  2. Вы отправляли сообщения только другому пользователю.
  3. Вы получили сообщения только от другого пользователя.

(«Вы» определяется как пользователь 12345, для которого вы извлекаете цепочки сообщений.)

Запрос Макс пропустил состояние # 3. Я обнаружил, что добавление предложения WHERE к запросу в INNER JOIN не только исправило это, но также ограничило результаты только теми потоками, которые связаны с пользователем 12345.

SELECT   m1.*
FROM     messages m1
         INNER JOIN (SELECT   MAX(time) AS time,
                              IF(receiver = 12345, sender, receiver ) AS user
                     FROM     messages
                     WHERE    sender_id = 12345 OR receiver_id = 12345
                     GROUP BY user) m2
           ON m1.time = m2.time AND (m1.sender = m2.user OR m1.receiver = m2.user)
WHERE    sender = 12345 OR receiver = 12345
ORDER BY m1.time DESC
0 голосов
/ 29 апреля 2010

Я думаю, что нашел решение, используя советы Макса Шавабке. Но на самом деле я думаю, что могу оптимизировать его.

SELECT *
FROM 

(
SELECT *
FROM messages
ORDER BY sendtime DESC
) messages2

WHERE receiver = @id_user
OR sender = @id_user
GROUP BY IF( receiver = @id_user, sender, receiver ) 

Я думаю, что есть лучшее решение ....

0 голосов
/ 29 апреля 2010

Возможно, вы ищете GROUP BY, хотя наличие отдельных полей для Sender и Receiver усложняет.

ИМХО было бы лучше иметь UserID и MessageDirection SET('IN','OUT' ).

Тогда вы могли бы сделать

SELECT UserID, MAX(time) GROUP BY UserID

Редактировать

Если вы хотите последние 10

SELECT UserID, MAX(time) GROUP BY UserID ORDER BY time LIMIT 10

Вероятно, это не самое быстрое решение, и его можно оптимизировать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...