先排序,再分组
First order by, then Group by
我有一个 table 消息 (person_id, 消息, conversation_id, created_at)
我想在每次对话中获取最新消息。我尝试使用子查询,但它似乎忽略了子查询中的 orderby:
SELECT sub.* FROM
(SELECT * FROM messages ORDER BY created_at DESC) AS sub
GROUP BY sub.conversation_id
在这个 SQLfiddle 中试试。
还有其他方法可以得到正确的结果吗?
试试这个方法:
SELECT m1.*
FROM messages AS m1
JOIN (
SELECT conversation_id, MAX(created_at) AS created_at
FROM messages
GROUP BY conversation_id
) AS m2 ON m1.conversation_id = m2.conversation_id AND m1.created_at = m2.created_at
无法在 sqlfiddle 上测试它,它对我不起作用:
SELECT m1.*
FROM messages m1
WHERE m1.created_at =
(SELECT max(created_at)
FROM messages m2
where m1.conversation_id=m2.conversation_id)
您可以使用 select 列表中的相关子查询来执行此操作,或者使用从列表中的子查询连接回您的主 table.
相关子查询:
SELECT DISTINCT m1.conversation_id, (SELECT * FROM messages m2 WHERE m2.conversation_id=m1.conversation_id ORDER BY created_at DESC LIMIT 1)
FROM messages m1
from 子句中的子查询:
SELECT m1.*
FROM messages as m1
JOIN (
SELECT conversation_id, max(created_at) AS max_created_at
FROM messages
GROUP BY conversation_id
) m2 on m1.conversation_id = m2.conversation_id and m1.created_at = m2.max_created_at
2 种方法的区别在于相关子查询总是 return 每个对话 ID 1 条记录。如果 2 条记录具有相同的 created_at 值,则第二个可能 return 每个对话的记录超过 1 条。如果有一个自动递增的 id 字段来唯一标识每条消息,那么您可以使用此字段的最大值而不是创建字段来解决此潜在问题。
如果您想要每个对话的所有最新消息,您可以在 select 分组依据
中使用 where in
SELECT messages.*
FROM messages
WHERE (messages.created_at, messages.conversation_id) in
(SELECT max(created_at) , conversation_id
FROM messages messages
Group by conversation_id);
我有一个 table 消息 (person_id, 消息, conversation_id, created_at)
我想在每次对话中获取最新消息。我尝试使用子查询,但它似乎忽略了子查询中的 orderby:
SELECT sub.* FROM
(SELECT * FROM messages ORDER BY created_at DESC) AS sub
GROUP BY sub.conversation_id
在这个 SQLfiddle 中试试。
还有其他方法可以得到正确的结果吗?
试试这个方法:
SELECT m1.*
FROM messages AS m1
JOIN (
SELECT conversation_id, MAX(created_at) AS created_at
FROM messages
GROUP BY conversation_id
) AS m2 ON m1.conversation_id = m2.conversation_id AND m1.created_at = m2.created_at
无法在 sqlfiddle 上测试它,它对我不起作用:
SELECT m1.*
FROM messages m1
WHERE m1.created_at =
(SELECT max(created_at)
FROM messages m2
where m1.conversation_id=m2.conversation_id)
您可以使用 select 列表中的相关子查询来执行此操作,或者使用从列表中的子查询连接回您的主 table.
相关子查询:
SELECT DISTINCT m1.conversation_id, (SELECT * FROM messages m2 WHERE m2.conversation_id=m1.conversation_id ORDER BY created_at DESC LIMIT 1)
FROM messages m1
from 子句中的子查询:
SELECT m1.*
FROM messages as m1
JOIN (
SELECT conversation_id, max(created_at) AS max_created_at
FROM messages
GROUP BY conversation_id
) m2 on m1.conversation_id = m2.conversation_id and m1.created_at = m2.max_created_at
2 种方法的区别在于相关子查询总是 return 每个对话 ID 1 条记录。如果 2 条记录具有相同的 created_at 值,则第二个可能 return 每个对话的记录超过 1 条。如果有一个自动递增的 id 字段来唯一标识每条消息,那么您可以使用此字段的最大值而不是创建字段来解决此潜在问题。
如果您想要每个对话的所有最新消息,您可以在 select 分组依据
中使用 where inSELECT messages.*
FROM messages
WHERE (messages.created_at, messages.conversation_id) in
(SELECT max(created_at) , conversation_id
FROM messages messages
Group by conversation_id);