Получение списка уникальных диалогов между пользователями, в MySQL

193
23 апреля 2022, 04:50

Имеется таблица переписки между пользователями такого типа.

CREATE TABLE `messages` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `from_id` int(11) DEFAULT NULL,
  `whom_id` int(11) NOT NULL,
  `message` varchar(750) NOT NULL,
  `status` int(11) DEFAULT 0,
  `is_delete_from` int(11) DEFAULT 0,
  `is_delete_whom` int(11) DEFAULT 0,
  `created_at` int(11) NOT NULL,
  `updated_at` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx-messages-from_id` (`from_id`),
  KEY `idx-messages-whom_id` (`whom_id`),
  CONSTRAINT `fk-messages-from_id-user-id` FOREIGN KEY (`from_id`) REFERENCES `users` (`id`),
  CONSTRAINT `fk-messages-whom_id-user-id` FOREIGN KEY (`whom_id`) REFERENCES `users` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;

INSERT INTO `messages` VALUES (1, 1, 4, 'Привет привет!', 1, 0, 0, 1603017286, 1603017286);
INSERT INTO `messages` VALUES (2, 1, 5, 'Сокол! Сокол! Я Песец!', 2, 0, 0, 1603017300, 1603017358);
INSERT INTO `messages` VALUES (3, 1, 5, 'Вижу танки! Нам ......', 2, 0, 0, 1603017370, 1603017370);
INSERT INTO `messages` VALUES (4, 5, 1, 'Ну привет, чего хотел?', 2, 0, 0, 1603017500, 1603017500);
INSERT INTO `messages` VALUES (5, 5, 2, 'Здравствуйте', 1, 0, 0, 1603035035, 1603035035);
INSERT INTO `messages` VALUES (6, 5, 2, 'Как ваши дела?', 1, 0, 0, 1603035236, 1603035236);
INSERT INTO `messages` VALUES (7, 5, 2, 'Проверка', 1, 0, 0, 1603035246, 1603035246);
INSERT INTO `messages` VALUES (8, 5, 1, 'Ну как дела', 2, 0, 0, 1603035280, 1603035280);
INSERT INTO `messages` VALUES (9, 5, 1, 'Вы тут?', 2, 0, 0, 1603045195, 1603045195);
INSERT INTO `messages` VALUES (10, 5, 2, 'Проверка связи', 1, 0, 0, 1603046241, 1603046241);
INSERT INTO `messages` VALUES (11, 5, 1, '123', 2, 0, 0, 1603049281, 1603049281);
INSERT INTO `messages` VALUES (12, 5, 1, '321', 2, 0, 0, 1603049286, 1603049286);

Пытаюсь получить список всех сообщений которые приходили пользователю 5, и которые он сам отправлял, одним запросом.

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

Мои мысли заканчиваются на таком запросе:

SELECT * FROM `messages` WHERE (`from_id`=5) OR (`whom_id`=5) GROUP BY `whom_id`

Можно ли сделать эту выборку одним запросом? Если да, то как, прошу помощи.

Я легко могу получить список тех кому я писал.

SELECT  messages.whom_id FROM   messages WHERE messages.from_id = 5 GROUP BY messages.whom_id

Я так же могу получить список, кто мне писал.

SELECT  messages.from_id FROM messages WHERE messages.whom_id = 5 GROUP BY messages.from_id

А как их объединить в один запрос, исключая совпадения

Answer 1

Просто список:

SELECT case when `from_id`=5 then whom_id else from_id end as contact_id 
FROM `messages` WHERE (`from_id`=5) OR (`whom_id`=5) GROUP BY `contact_id`

То есть определяем второго собеседника (отличающегося от самого себя - уже знаем) и группируем по этому полю.

Если список надо получать часто/быстро - лучше заведите явную таблицу для диалогов, а не пытайтесь посчитать их по куда более большой таблице сообщений. Там же в таблице диалогов сможете хранить ссылку на последнее сообщение в переписке чтобы сразу его join'ом доставать и выводить.

READ ALSO
Как выбрать запись которой соответствует наибольшее значение в другой таблице?

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

Пытаюсь реализовать запрос, в котором хочу вывести ФИО работника, который выполнил самое большое количество заказов (объектов)

208
Карусель карточек bootstrap

Карусель карточек bootstrap

Необходимо сделать вывод карточек в карусельЯ сделал вот такую вот

234
Spring Boot + DB транзакции

Spring Boot + DB транзакции

Недавно начал изучать Spring и возник такой вопросВ Spring Boot при выполнении длительного метода, как сделать, чтобы @Transactional метод блокировал (ставил...

161