Показывать только последние сообщения из каждого разговора - PullRequest
0 голосов
/ 23 октября 2018

У меня есть система обмена сообщениями, в которой есть таблицы «message», в которой просто содержится «subject», а затем «message_user», в котором содержится тело сообщения, кто его отправил, кому оно предназначено, и было ли оно удалено / непрочитано.

#Message Table

CREATE TABLE `message` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `subject` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;

INSERT INTO `message` (`id`, `subject`)
VALUES
    (1, 'Test'),
    (2, 'Test Again');

#Message User Table

CREATE TABLE `message_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `message_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `interlocutor` int(11) DEFAULT NULL,
  `body` text,
  `folder` enum('inbox','sent') NOT NULL,
  `starmark` tinyint(1) NOT NULL DEFAULT '0',
  `unread` tinyint(1) NOT NULL DEFAULT '1',
  `deleted` enum('none','trash','deleted') NOT NULL DEFAULT 'none',
  `date` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;

INSERT INTO `message_user` (`id`, `message_id`, `user_id`, `interlocutor`, `body`, `folder`, `starmark`, `unread`, `deleted`, `date`)
VALUES
    (1, 1, 1, 2, 'Hi, how are you?', 'sent', 0, 1, 'none', '2018-10-23 09:36:02'),
    (2, 1, 2, 1, 'Hi, how are you?', 'inbox', 0, 1, 'none', '2018-10-23 09:36:02'),
    (3, 1, 2, 1, 'I am good thanks, you?', 'sent', 0, 1, 'none', '2018-10-23 09:46:02'),
    (4, 1, 1, 2, 'I am good thanks, you?', 'inbox', 0, 1, 'none', '2018-10-23 09:46:02'),
    (5, 2, 1, 3, 'Hi!', 'sent', 0, 1, 'none', '2018-10-23 09:50:22'),
    (6, 2, 3, 1, 'Hi!', 'inbox', 0, 1, 'none', '2018-10-23 09:50:22');

Я написал следующий запрос:

SELECT
    *
FROM message m
JOIN message_user mu ON m.id = mu.message_id
WHERE mu.deleted = 'none'
    AND mu.user_id = 1 #user_id of person checking messages
ORDER BY mu.id DESC;

Но в настоящее время возвращается 3 строки, хотя разговоров только два.Я пытался выполнить GROUP BY, но он по-прежнему отображал 3 строки.

enter image description here

Я ожидаю, что первые две строки в приведенном выше примере не будут последними.

Я хочу, чтобы запрос возвратил список разговоров с последним отправленным сообщением, в котором я (user_id) участвую.

Ответы [ 2 ]

0 голосов
/ 23 октября 2018
  • Поскольку ваша версия MySQL равна 8.0+, мы можем использовать оконные функции , такие как Row_number();в противном случае решение было бы очень многословным, с использованием переменных Session .
  • Для раздела (группы) из m.id мы определим значения номеров строк.Значения номеров строк будут упорядочены в порядке убывания date.
  • Теперь нам просто нужно использовать этот набор результатов как Производная таблица , и просто рассмотреть те строки, где номер строкизначение равно 1.
  • Date - это ключевое слово в MySQL .Вы должны избегать именования столбца / таблицы, используя его.Тем не менее, если вам нужно сделать это, вам нужно будет использовать обратные метки вокруг него.

Попробуйте следующее ( DB Fiddle DEMO ):

SELECT  dt.*
FROM (
      SELECT  m.id,
              m.subject,
              mu.id AS message_user_id,
              mu.message_id,
              mu.user_id,
              mu.interlocutor,
              mu.body,
              mu.folder,
              mu.starmark,
              mu.unread,
              mu.deleted,
              mu.`date`,
              Row_number()
                OVER (PARTITION BY m.id 
                      ORDER BY mu.`date` DESC) AS row_no
        FROM  message m
        JOIN  message_user mu
          ON  m.id = mu.message_id
        WHERE mu.deleted = 'none'
          AND mu.user_id = 1 ) AS dt
WHERE    dt.row_no = 1
ORDER BY dt.id DESC 
0 голосов
/ 23 октября 2018

Попробуйте:

select 
    m.id as id_message, m.subject as subject_message,
    mu.id as id_message_user, mu.interlocutor, mu.body, mu.folder, mu.starmark, mu.deleted, mu.date 
from message as m
inner join message_user as mu on mu.message_id = m.id and mu.deleted = 'none' and mu.user_id = 1
group by id_message
order by id_message_user desc

Я удалил

  • mu.user_id : он находится в состоянии внутреннего соединения, поэтому всегда 'none'
  • mu.unread : то же, всегда 1
  • mu.message_id : дубликат id_message

http://sqlfiddle.com/#!9/91a5e4/15

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