使用GROUP BY进行MySQL查询,使用ORDER BY进行子查询

时间:2014-05-27 11:51:31

标签: php mysql sql

我有一个消息表,每个消息都属于一个唯一的对话(conversation_id)。我想从每个对话中选择最新消息。

下面的查询有效,但由于子查询选择了发送给用户的所有邮件,因此效率似乎非常低。

SELECT
    conversation_id,
    to_id,
    from_id,
    time_sent,
    type,
    message
FROM (
    SELECT
        *
    FROM
        messages
    WHERE
        to_id = :uid
    OR
        from_id = :uid
    ORDER BY
        time_sent
    DESC
)
AS
    t1
GROUP BY
    conversation_id
ORDER BY
    time_sent
DESC

如果我只包含GROUP BY,则会选择第一行(最旧的)行:

SELECT
    conversation_id,
    to_id,
    from_id,
    time_sent,
    type,
    message
FROM
    messages
WHERE
    to_id = :uid
OR
    from_id = :uid
GROUP BY
    conversation_id

但是当我在同一个查询中执行GROUP BYORDER BY时,它会返回每个会话中的第一个(最旧的)行,而不是最后一个,因此ORDER BY不是'工作或不做我期望的事。

SELECT
    conversation_id,
    to_id,
    from_id,
    time_sent,
    type,
    message
FROM
    messages
WHERE
    to_id = :uid
OR
    from_id = :uid
GROUP BY
    conversation_id
ORDER BY
    time_sent
DESC

我非常确定我需要子查询,但是如何在不先选择所有邮件的情况下执行此操作?

3 个答案:

答案 0 :(得分:2)

这可能是您寻找的方式

SELECT *
FROM messages
WHERE conversation_id = (
 SELECT id
 FROM conversations
 WHERE id={insert id here...}
 LIMIT 0,1)
ORDER BY id DESC

我假设您按会话ID选择。

答案 1 :(得分:2)

尝试将此表与每个对话的conversation_id和max(time_sent)子查询结合起来:

SELECT
    m.conversation_id,
    m.to_id,
    m.from_id,
    m.time_sent,
    m.type,
    m.message
FROM messages as m
JOIN 
   (SELECT  conversation_id,
            MAX(time_sent) as MAX_time_sent
    FROM  messages
    WHERE to_id = :uid  OR from_id = :uid
    GROUP BY conversation_id
   ) AS t1
   ON m.conversation_id=t1.conversation_id AND m.time_sent = t1.MAX_time_sent

ORDER BY m.time_sent DESC

答案 2 :(得分:1)

这样的事情会这样做(假设to_id和from_id对话是一致的): -

SELECT messages.conversation_id,
    messages.to_id,
    messages.from_id,
    messages.time_sent,
    messages.type,
    messages.message
FROM 
(
    SELECT conversation_id, MAX(time_sent) AS max_time_sent
    FROM messages
    GROUP BY conversation_id
) t1
INNER JOIN messages
ON t1.conversation_id = messages.conversation_id
AND t1.max_time_sent = messages.time_sent
WHERE messages.to_id = :uid
OR messages.from_id = :uid