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