MySQL: получить последнее сообщение из 2 таблиц, которые связаны друг с другом - PullRequest
0 голосов
/ 18 ноября 2018

Во-первых, большое спасибо за вашу помощь.

У меня есть 2 таблицы: таблица conversation и таблица message, а также третья таблица assoc_message__conversation, которая связывает сообщения с беседой.

Мне нужно получить последние message_id и message, отправленные для каждого указанного разговора, вместе с conversation_id, с которым он связан.

Вот дд-скрипта: https://www.db -fiddle.com / f / kxRQeGUYYgQ7FTwi96hbLp / 0

Как вы можете видеть в этом примере, есть две беседы с conversation_id из 1 и 2, и с каждой беседой связаны три сообщения. Сообщения 1, 2 и 3 связаны с беседой 1, а сообщения 4, 5 и 6 связаны с беседой 2.

Мне нужно иметь возможность указать conversation_id в таблице assoc_message__conversation (идентификаторы 1 и 2) и извлечь последние message_id, message и связанные conversation_id, отправленные из message таблица для каждого указанного разговора.

Итак, строки, которые он должен вытащить:

conversation_id | message_id | message
------------------------------------------------
              1 |          3 | "Latest message"
------------------------------------------------
              2 |          6 | "Latest message"
------------------------------------------------

Большое вам спасибо за помощь!

Ответы [ 2 ]

0 голосов
/ 18 ноября 2018

В более старых версиях MySQL (<8.0.2) мы можем использовать <a href="https://dev.mysql.com/doc/refman/8.0/en/derived-tables.html" rel="nofollow noreferrer"> Производные таблицы .В производной таблице мы можем получить самое последнее значение send_datetime для каждого conversation_id. Кроме того, следует отметить, что вы можете предоставить свои фильтры дляослова_идеоза в условии WHERE этого подзапроса.

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

Схема (MySQL v5.7)

Просмотр в БД Fiddle

Запрос # 1

SELECT
  amc.conversation_id, 
  m.message_id, 
  m.message   
FROM 
  assoc_message__conversation AS amc
JOIN message AS m 
  ON m.message_id = amc.message_id 
JOIN 
(
  SELECT
    amc1.conversation_id, 
    MAX(m1.send_datetime) AS latest_send_datetime
  FROM
   assoc_message__conversation AS amc1
  JOIN message AS m1
    ON m1.message_id = amc1.message_id 
  WHERE amc1.conversation_id IN (1,2)  -- Here you provide your input filters
  GROUP BY amc1.conversation_id
) AS dt  
  ON dt.conversation_id = amc.conversation_id AND 
     dt.latest_send_datetime = m.send_datetime;

Результат

| conversation_id | message_id | message        |
| --------------- | ---------- | -------------- |
| 1               | 3          | Latest message |
| 2               | 6          | Latest message |

В MySQL 8.0.2 и выше, мы можем использовать Row_Number() функциональность.В пределах раздела conversation_id мы определим номер строки для каждого сообщения, отсортированного в порядке убывания send_datetime. В этом подзапросе вы можете предоставить свои фильтры дляослова в предложении WHERE.

Затем мы будем использовать этот набор результатов в качестве производной таблицы и рассматривать только те строки, гдеЗначение номера строки равно 1 (так как оно будет принадлежать последней send_datetime).

Схема (MySQL v8.0)

Просмотр на БД Fiddle

Запрос № 2

SELECT 
  dt.conversation_id, 
  dt.message_id, 
  dt.message 
FROM 
(
  SELECT
    amc.conversation_id, 
    m.message_id, 
    m.message, 
    ROW_NUMBER() OVER (PARTITION BY amc.conversation_id 
                       ORDER BY m.send_datetime DESC) AS row_no 
  FROM
   assoc_message__conversation AS amc
  JOIN message AS m
    ON m.message_id = amc.message_id 
  WHERE amc.conversation_id IN (1,2)  -- Here you provide your input filters
) AS dt  
WHERE dt.row_no = 1;

Результат

| conversation_id | message_id | message        |
| --------------- | ---------- | -------------- |
| 1               | 3          | Latest message |
| 2               | 6          | Latest message |
0 голосов
/ 18 ноября 2018

Если предположить, что amc_id увеличивается для каждого нового сообщения, я бы рекомендовал коррелированный подзапрос в предложении where:

select amc.*, m.message
from message m join
     assoc_message__conversation amc
     on amc.message_id = m.message_id
where amc.amc_id = (select max(amc.amc_id)
                    from assoc_message__conversation amc2
                    where amc2.conversation_id = amc.conversation_id
                   );

Если вам действительно нужно использовать send_datetime, тогда необходимо добавить join:

where m.send_datetime = (select max(m2.send_datetime)
                         from message m2 join
                              assoc_message__conversation amc2
                              on amc2.message_id = m2.message_id
                         where amc2.conversation_id = amc.conversation_id
                        )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...