@dhscor

Как выбрать две последнии записи для каждой группы?

Помогите, пожалуйста, составить запрос для выбора двух последних сообщений для каждого диалога? Таблица:

+----+--------+-----+-----+-------+-----------+
| id |group-id|user1|user2|message|last-sender|
+----+--------+-----+-----+-------+-----------+

В каждом диалоге, пользователь может отправить лишь одно сообщение, т.е диалог выглядит примерным образом:

user1: message from user1.
user2: message from user2.
user1: message from user1.
user2: message from user2.
e.t.c

Соответственно, желаемый результат, чтобы последнее сообщение было всегда от пользователя != $_SESSION['ID'], а предпоследнее от пользователя = $_SESSION['ID'].

Подобным образом я хочу вывести привью диалогов, не больше 20 штук на странице:
+-------------------------------------------------------+
|                         ДИАЛОГ 1                      |
+--------+-------------+--------------------------------+
|  user1 | hello world | last-sender = $_SESSION['ID']  |
+--------+-------------+--------------------------------+
|  user2 |   hi! :)    | last-sender != $_SESSION['ID'] |
+--------+-------------+--------------------------------+

+-------------------------------------------------------+
|                         ДИАЛОГ 2                      |
+--------+-------------+--------------------------------+
|  user2 | what's up?  | last-sender = $_SESSION['ID']  |
+--------+-------------+--------------------------------+
|  user1 |   sup       | last-sender != $_SESSION['ID'] |
+--------+-------------+--------------------------------+

Я перепробовал уже тысячи способов, но прийти к нужному результату у меня так и не получилось. Может ли кто-нибудь, пожалуйста, помочь? А то я застрял на этом участке кода уже около недели. :(
  • Вопрос задан
  • 89 просмотров
Решения вопроса 2
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Для MySQL 8:
SELECT *
  FROM (
    SELECT `id`, `group-id`, `user1`, `user2`, `message`,
           ROW_NUMBER() OVER (PARTITION BY `group-id` ORDER BY `id` DESC) AS `row_number`
    FROM `messages`
  ) AS `t`
  WHERE `row_number` < 3
  ORDER BY `group-id`, `id`
Ответ написан
rozhnev
@rozhnev
Fullstack programmer, DBA, медленно, дорого
Вот такая сложная конструкция для MySQL 5.x:
select * 
from messages 
join (
  select 
        -- создаем JSON ARRAY из id и берем 2 последних элемента
	IF (
	  JSON_LENGTH(json_arrayagg(id))>2,
	  JSON_EXTRACT(json_arrayagg(id), CONCAT("$[",JSON_LENGTH(json_arrayagg(id))-2,"]"), CONCAT("$[",JSON_LENGTH(json_arrayagg(id))-1,"]")),
	  json_arrayagg(id)
	) ids,
	group_id
  from 
	messages
  group by group_id
) last_messages on json_contains(ids, CAST(messages.id AS JSON))
;

SQL песочница
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
FanatPHP
@FanatPHP
Чебуратор тега PHP
Мне кажется, можно и без оконных функций
каким-нибудь select max(id) group by group-id получить айдишники последних 20 разговоров, соответственно этим подзапросом выбрать все последние реплики, ну и еще один подзапрос чтобы выбрать реплику второго адресата
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы