Получить все последние сообщения от каждого друга - SQL - PullRequest
0 голосов
/ 15 мая 2018

Я пытаюсь выбрать последнее сообщение от каждого друга так же, как и все другие приложения чата. Вот что у меня есть.

SELECT m.message, 
                   m.message_read,
                   m.message_date,
                   CASE WHEN m.sender = 4
                        THEN m.receiver
                        ELSE m.sender
                   END as friend_id,
                   CASE WHEN m.sender = 4
                        THEN p2.nickname
                        ELSE p1.nickname
                   END as name,
                   CASE WHEN m.sender = 4
                        THEN p2.image
                        ELSE p1.image
                   END as image
            FROM message as m
            JOIN profile as p1
              ON m.sender = p1.user_id    -- sender
            JOIN profile as p2 
              ON m.receiver = p2.user_id  -- receiver
            WHERE 4 IN (m.sender, m.receiver)

Приведенный выше оператор выбора получает

+-----------+--------------+---------------------+-----------+-------+-------+
| message   | message_read | message_date        | friend_id | name  | image |
+-----------+--------------+---------------------+-----------+-------+-------+
| Hey Buddy |            1 | 2018-05-10 11:58:39 |         1 | JUAN  | NULL  |
| SUP MATE  |            1 | 2018-05-15 11:04:24 |         1 | JUAN  | NULL  |
| nooo      |            1 | 2018-05-15 10:24:36 |         2 | user3 | NULL  |
| lulz      |            1 | 2018-05-15 10:24:36 |         2 | user3 | NULL  |
| shut up   |            1 | 2018-05-15 10:24:36 |         2 | user3 | NULL  |
| heha      |            1 | 2018-05-15 10:36:11 |         2 | user3 | NULL  |
+-----------+--------------+---------------------+-----------+-------+-------+

Я специально использую переменную message_date из таблицы сообщений для сортировки этих сообщений.

таблица сообщений:

+----+--------+----------+-----------+--------------+-----------------+---------------------+
| id | sender | receiver | message   | message_read | message_visible | message_date        |
+----+--------+----------+-----------+--------------+-----------------+---------------------+
|  1 |      4 |        2 | lulz      |            1 |               2 | 2018-05-15 10:24:36 |
|  2 |      1 |        4 | Hey Buddy |            1 |            NULL | 2018-05-10 11:58:39 |
|  3 |      2 |        4 | nooo      |            1 |               2 | 2018-05-15 10:24:36 |
|  4 |      4 |        2 | shut up   |            1 |               2 | 2018-05-15 10:24:36 |
|  5 |      4 |        2 | heha      |            1 |            NULL | 2018-05-15 10:36:11 |
|  6 |      1 |        4 | SUP MATE  |            1 |            NULL | 2018-05-15 11:04:24 |
+----+--------+----------+-----------+--------------+-----------------+---------------------+

Я бы хотел получить результат

+-----------+--------------+---------------------+-----------+-------+-------+
| message   | message_read | message_date        | friend_id | name  | image |
+-----------+--------------+---------------------+-----------+-------+-------+
| SUP MATE  |            1 | 2018-05-15 11:04:24 |         1 | JUAN  | NULL  |
| heha      |            1 | 2018-05-15 10:36:11 |         2 | user3 | NULL  |
+-----------+--------------+---------------------+-----------+-------+-------+

Пожалуйста, помогите мне понять это. Любой комментарий будет полезен! Это также должно учитывать ту же дату сообщения. например если есть два сообщения с одинаковой датой / временем, то среди них должно быть выбрано только одно. Я думаю об идентификаторе таблицы сообщений, чтобы выбрать какой из них.

Ответы [ 2 ]

0 голосов
/ 15 мая 2018

использовать row_number и разделить на.

select * from
(SELECT m.message, 
               m.message_read,
               m.message_date,
               CASE WHEN m.sender = 4
                    THEN m.receiver
                    ELSE m.sender
               END as friend_id,
               CASE WHEN m.sender = 4
                    THEN p2.nickname
                    ELSE p1.nickname
               END as name,
               CASE WHEN m.sender = 4
                    THEN p2.image
                    ELSE p1.image
               END as image,
       ROW_NUMBER() OVER (PARTITION BY friend_id ORDER BY m.message_date DESC) AS rn               
        FROM message as m
        JOIN profile as p1
          ON m.sender = p1.user_id    -- sender
        JOIN profile as p2 
          ON m.receiver = p2.user_id  -- receiver
        WHERE 4 IN (m.sender, m.receiver)
) t
where rn=1
0 голосов
/ 15 мая 2018

В некотором роде

select m.*
from 
message m
left join message m1 on (
  (
    (m.sender = m1.sender and m.receiver = m1.receiver)
                          or
    (m.sender = m1.receiver and m.receiver = m1.sender )
  )
   and case when m.message_date = m1.message_date
            then m.id < m1.id
            else m.message_date < m1.message_date
       end
)
where m1.id is null
and 4 in(m.sender, m.receiver)

Я добавил выражение case, чтобы проверить, есть ли более 1 сообщения в одно и то же время, затем выберите последнее сообщение на основе идентификатора. Я предполагаю, что для id установлено значениеавтоинкремент.

Демо

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