1

我试图编写一个收件箱,按收到的顺序显示消息,然后按是否已阅读,它似乎工作了一段时间,但不是没有。它可能只在某些情况下有效,也许..

无论如何,这是我的查询;

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(sent)。

我的逻辑错了吗?或者我可以排序然后分组,因为我所有的努力都导致“每个派生表都必须有自己的别名”

4

4 回答 4

4

设置一个 SQL Fiddle - 这是我想出的最好的。基本上我先在子查询中进行排序,然后再对它们进行分组。这似乎适用于我输入的(有限的)测试数据。

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

看小提琴玩:http ://sqlfiddle.com/#!2/4f63d/8

于 2012-06-05T20:54:57.057 回答
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)(除了先前的索引之外)创建一个索引。

于 2012-06-05T20:32:06.357 回答
2

正如 Quassnoi 所说,您正在使用 GROUP BY 查询并在“读取”上排序,这不是聚合函数。因此,您无法确定 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;

(我使用了 Andy Jones 的小提琴模式:http ://sqlfiddle.com/#!2/4f63d/8 。
顺便说一句,非常感谢 Andy,这个网站很棒!)

希望这有帮助!

于 2012-06-06T09:41:20.650 回答
1

“收件箱按收到的顺序显示消息,然后按它们是否已被阅读......但是它应该是最新消息” - 假设 read 是一个可以为空的日期/时间列,并且消息存储在它们被发送的顺序(新的 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
于 2012-06-05T20:42:23.400 回答