MySQL对数据进行排序

时间:2012-06-05 20:11:43

标签: mysql

我曾尝试对收件箱进行编程,按收到的顺序显示邮件,然后如果已经阅读过,它似乎工作了一段时间,但事实并非如此。它可能只在某些情况下才有效。

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

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(已发送)。

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

4 个答案:

答案 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

请参阅小提琴:http://sqlfiddle.com/#!2/4f63d/8

答案 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