我曾尝试对收件箱进行编程,按收到的顺序显示邮件,然后如果已经阅读过,它似乎工作了一段时间,但事实并非如此。它可能只在某些情况下才有效。
无论如何,这是我的询问;
SELECT `id`, `from_userid`, `read`, max(sent) AS sent
FROM (`who_messages`)
WHERE `to_userid` = '41'
GROUP BY `from_userid`
ORDER BY `read` ASC, `sent` DESC
我认为问题在于消息按错误顺序分组..因为当新消息存在时,收件箱始终显示为已读。我得到了新消息的正确时间,但我猜这是因为我选择了max(已发送)。
我的逻辑错了吗?或者我可以排序然后分组,因为我的所有努力都导致'每个派生表必须有自己的别名'
答案 0 :(得分:4)
设置一个SQL小提琴 - 这是我提出的最好的。基本上我先在子查询中进行排序,然后将它们分组。这似乎适用于我输入的(有限的)测试数据。
SELECT *
FROM (SELECT id, from_userid, is_read, sent
FROM who_messages
WHERE to_userid = 41
ORDER BY from_userid ASC, is_read ASC) m
GROUP BY m.from_userid
ORDER BY m.is_read ASC, m.sent DESC
答案 1 :(得分:2)
您正在分组查询中选择非分组字段。无法保证会返回该组的哪个记录,ORDER BY
之后会处理GROUP BY
。
试试这个:
SELECT m.*
FROM (
SELECT DISTINCT from_userid
FROM who_messages
WHERE to_userid = 41
) md
JOIN who_messages m
ON m.id =
(
SELECT mi.id
FROM who_message mi
WHERE (mi.to_userid, mi.from_userid) = (41, md.from_userid)
ORDER BY
mi.sent DESC, mi.id DESC
LIMIT 1
)
在who_message (to_userid, from_userid, sent, id)
上创建一个索引,以便快速工作。
<强>更新强>
上述查询将返回来自任何给定用户的最后一条消息的记录(包括其读取状态)。如果要检查是否有来自用户的任何未读消息,请使用:
SELECT m.*, md.all_read
FROM (
SELECT from_userid, MIN(read) AS all_read
FROM who_messages
WHERE to_userid = 41
GROUP BY
from_userid
) md
JOIN who_messages m
ON m.id =
(
SELECT mi.id
FROM who_message mi
WHERE (mi.to_userid, mi.from_userid) = (41, md.from_userid)
ORDER BY
mi.sent DESC, mi.id DESC
LIMIT 1
)
为了快速工作,请在who_message (to_userid, from_userid, read)
上创建一个索引(除了之前的索引)。
答案 2 :(得分:2)
正如Quassnoi所说,您正在使用GROUP BY查询并在'read'上订购,而不是aggregate function。因此,您无法确定MySQL引擎使用的值(通常是组的最后一个,但是......)
我建议以这种方式编写查询,因为它不涉及任何子查询,并且还有许多其他性能友好的用法:
SELECT
from_userid,
COUNT(*) AS nb_messages,
SUM(NOT is_read) AS nb_unread_messages,
MAX(sent) AS last_sent
FROM who_messages
WHERE to_userid = 41
GROUP BY from_userid
ORDER BY nb_unread_messages DESC, last_sent DESC;
(我使用安迪琼斯的小提琴架构:http://sqlfiddle.com/#!2/4f63d/8 顺便说一句,非常感谢Andy,这个网站很棒!)
希望这有帮助!
答案 3 :(得分:1)
“收件箱按照收到的顺序显示邮件,然后是否已被阅读...但是它被认为是最新邮件” - 假设读取是可以为空的日期/时间列,并且邮件按照发送的顺序存储(较新的ID大于较旧的 - autoid)
SELECT wm.id, wm.from_userid, (wm.read IS NULL) as unread, wm.sent
FROM (SELECT MAX(id) AS id FROM who_messages WHERE to_userid = '41' GROUP BY from_userid) sub
INNER JOIN who_messages wm ON sub.id = wm.id
ORDER BY wm.sent DESC, wm.read