Mysql: получение последней строки из объединенной таблицы - PullRequest
1 голос
/ 16 июня 2011

Я знаю, что этот вопрос задавался много раз, но у меня возникли проблемы с его реализацией. MySQL не моя самая большая сила здесь.

Я создал систему электронной почты для своего сайта, и я хочу, чтобы, когда пользователь просматривает свою папку «Входящие», он видел свои сообщения, однако вместо оригинала он видел последние сведения об отправителе, дате и пользователе для этого конкретного сообщения. отправитель, дата и данные пользователя.

Моя структура таблицы выглядит следующим образом:

Message_Header

-----------------------
messageid    INT
type         VARCHAR
subject      VARCHAR

Message_Recipient

-----------------------
id           INT
messageid    INT
userid       INT
isread       ENUM
isspam       ENUM
isdelete     ENUM

Message_Detail

--------------------
dtlid        INT
messageid    INT
from_userid  INT
hash         VARCHAR
type         SMALLINT
body         TEXT
title        VARCHAR
subtitle     VARCHAR
content      TEXT
thumb        VARCHAR
url          TEXT
images       VARCHAR
time_sent    DATETIME
timestamp    INT

Я думал, что-то вроде этого будет работать:

select mh.messageid, mh.subject, mh.type, mr.isread, msg_dtl.from_userid, msg_dtl.firstname, msg_dtl.lastname, msg_dtl.gender, msg_dtl.avatar, msg_dtl.hash, msg_dtl.body, msg_dtl.time_sent
from message_header mh
inner join message_recipient mr on mr.messageid = mh.messageid  
inner join (
    select md.messageid, md.from_userid, u.firstname, u.lastname, u.gender, u.avatar, md.hash, md.body, md.time_sent
    from message_detail md
    inner join users u on u.userid = md.from_userid
    order by md.time_sent desc
    limit 1
) as msg_dtl ON mh.messageid = msg_dtl.messageid
where mr.userid = 5
and mr.isspam = '0'
and mr.isdelete = '0'

Но, очевидно, он ограничивает общий запрос только одной строкой!

Я много раз оглядывался по сторонам, и все это вместе, но я боюсь, что это не оптимизировано и станет боровом:

SELECT msg_dtl.type, msg_dtl.subject, msg_dtl.isread, u.firstname, u.lastname, u.gender, u.avatar, md.body, md.timestamp 
FROM message_detail md
INNER JOIN users u on u.userid = md.from_userid     
INNER JOIN
(
    SELECT mr.userid, mh.type, mh.subject, mr.isspam, mr.isdelete, mr.isread, md.messageid, md.body, max(timestamp) as timestamp
    FROM message_detail md
    inner join message_header mh on mh.messageid = md.messageid
    inner join message_recipient mr on mr.messageid = mh.messageid  
    GROUP BY md.messageid
) as msg_dtl
USING (timestamp, messageid)
where msg_dtl.userid = 5
and msg_dtl.isspam = '0'
and msg_dtl.isdelete = '0'

Буду признателен за любые указатели или кто-то оптимизирует это. если вам нужна дополнительная информация, пожалуйста, дайте мне знать!

1 Ответ

0 голосов
/ 17 июня 2011

Это может помочь с одним исключением ... флаг IsRead.

Во-первых, я начинаю с "PreQuery", чтобы получить на основе одного сообщения (присоединенного к таблице подробностей), наиболеенедавняя последовательность в сообщении (через max (mr.id)) и последняя созданная запись DETAIL (при условии автоматического увеличения деталей через Max (md.DtlID)) только для тех записей для данного пользователя, которые не являются спамом и не удалены,Таким образом, это дает нам в МОСТе одну запись для каждого идентификатора сообщения.

При этом мы можем теперь выполнить прямое присоединение к заголовку идентификатора сообщения 1: 1, присоединиться

Затем,Присоединение 1: 1 НАЗАД К получателю сообщения с самой последней полученной последовательностью ... если цепное сообщение отправляется туда и обратно более 10 раз, то здесь я предположил, что вы предполагали, что самое последнее полученное сообщение электронной почты будет связано с идентификатором сообщения.Таким образом, это была запись, которую мы получаем с флагом IsRead ... хотя кто-то мог прочитать более свежую, но никогда не читал априор в цепочке писем.

Далее, 1: 1 присоединиться кТаблица MESSAGE DETAIL (через Max (md.DtlID)) для последней детали сообщения ЗА данное сообщение.Нам не нужно присоединяться к идентификатору сообщения, так как у нас есть ДЕТАЛЬНЫЙ идентификатор сообщения напрямую ...

Наконец, наша деталь может затем присоединиться к таблице пользователей, чтобы получить информацию о пользователе "От".

Надеюсь, это поможет, в том числе разъяснения о том, как получить набор результатов ...

SELECT STRAIGHT_JOIN
      PreQuery.MessageID,
      mr2.IsRead,
      mh.Type,
      mh.Subject,
      md.from_UserID,
      md.isread,
      md.body, 
      md.timestamp,
      u.firstname, 
      u.lastname, 
      u.gender, 
      u.avatar
   from
      ( SELECT
              mr.MessageID,
              MAX( mr.ID ) as LastMessageSequence,
              MAX( md.DtlID ) as LastDetail
           from
              Message_Recipient mr
                 join Message_Detail md
                    ON mr.messageid = md.messageid
           where
                  mr.userid = 5
              and mr.isspam = '0'
              and mr.isdelete = '0'
           group by
              mr.MessageID ) PreQuery

      JOIN Message_Recipient mr2
         ON PreQuery.LastMessageSequence = mr2.ID

      JOIN Message_Header mh
         ON PreQuery.MessageID = mh.MessageID

      JOIN Message_Detail md
         ON PreQuery.LastDetail = md.DtlID
         JOIN users u 
            on md.from_userid = u.userid

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