Mysql:从连接表中获取最后一行

标签 mysql subquery

我知道这个问题已经被问过很多次了,但我在实现它时遇到了麻烦。 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'

但显然它将整个查询限制为仅 1 行!

我四处看了看,把它拼凑在一起,但我担心它没有优化,会很麻烦:

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'

我将不胜感激任何指点或有人对此进行优化。如果您需要更多信息,请告诉我!

最佳答案

这可能对一个异常(exception)有帮助... IsRead 标志。

首先,我从一个“PreQuery”开始,它基于单个消息(连接到详细信息表)、消息中的最新序列(通过 max(mr.id) )和最新的 DETAIL创建的条目(假设通过 Max( md.DtlID ) 自动递增详细信息)仅为给定用户的那些不是垃圾邮件且未删除的记录创建的。因此,这最多为我们提供了每个消息 ID 一条记录。

也就是说,我们现在可以直接连接回消息 ID 上的 header 1:1 连接

然后,1:1 加入 BACK TO 消息收件人在最近收到的序列中...如果链式消息来回 10 次以上,这里是我假设您希望收到的最新电子邮件关联的位置带有消息 ID。因此,这是我们获得“IsRead”标志的记录......即使有人可以阅读更新的内容,但从未阅读过电子邮件链中的先前内容。

接下来,1:1 加入 MESSAGE DETAIL 表(通过 Max(md.DtlID))获取给定消息的最后一条消息详细信息。我们不必加入消息 ID,因为我们直接拥有消息的详细 ID...

最后,我们的详细信息可以连接到用户表以获取“发件人”用户信息。

希望这会有所帮助,包括对如何导出结果集的说明......

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

关于Mysql:从连接表中获取最后一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6377308/

相关文章:

php - 根据第一个表的id查询多个表

php - 如何检查一个值是否已经存在以避免重复?如果存在则什么都不做,否则将记录插入数据库

python - 如何使用 MySQLdb 从 Python 更改 SQL 隔离级别?

php - 将上传图像的路径更新到数据库中

mysql - 错误代码: 1064 | Delimiter

sql - Oracle SQL中结合LIMIT子句访问主表字段的子查询

php - 将多行从一个表传输到另一个表

mysql - SQL 嵌套查询解释为相关性不正确

mysql - 通过子查询同一个表创建 View

mysql - 你能索引子查询吗?