我在Hibernate中为消息传递组件创建一个SQL查询。我的想法是我要查询用户的对话,并按上次发送消息的日期排序。
我有两个表:conversations
messages
在我的选择查询中,我正在尝试类似的操作,但是在发送的最后一条消息中,排序从未发生。
String sql =
"SELECT * FROM conversations " +
"JOIN messages ON messages.conversation_id = conversations.id "+
"WHERE (conversations.creator_id = :userId OR conversations.to_id = :userId)" +
"GROUP BY messages.conversation_id "+
"ORDER BY messages.created DESC";
最佳答案
此问题是由于GROUP BY
子句的行为在MySQL特定的扩展引起的。其他数据库将引发错误……类似于SELECT列表中的聚合。”(如果在sql_mode中包含ONLY_FULL_GROUP_BY,我们可以使MySQL引发类似的错误。)
表达式messages.created
的问题是引用GROUP BY中不确定行中的值。 ORDER BY操作在GROUP BY操作之后的处理过程中发生得多。
要获取为每个组创建的“最新”消息,请使用聚合表达式MAX(messages.created)
。
要从同一行中获取其他值,要复杂一些。
假设created
在给定的conversation_id
组中是唯一的(或者,如果不能保证它不是唯一的,则可以为created
返回具有相同值的多行...
获取每个created
的最新conversation_id
SELECT lm.conversation_id
, MAX(lm.created) AS created
FROM conversation lc
JOIN message lm
ON lm.conversation_id = lc.id
WHERE (lc.creator_id = :userId OR lc.to_id = :userId)
GROUP BY lm.conversation_id
您可以将其用作内联视图,以使用最新的
created
获取整行SELECT c.*
, m.*
FROM ( SELECT lm.conversation_id
, MAX(lm.created) AS created
FROM conversation lc
JOIN message lm
ON lm.conversation_id = lc.id
WHERE (lc.creator_id = :userId OR lc.to_id = :userId)
GROUP BY lm.conversation_id
) l
JOIN conversation c
ON c.id = l.conversation_id
JOIN messages m
ON m.conversation_id = l.conversation_id
AND m.created = l.created
WHERE (c.creator_id = :userId OR c.to_id = :userId)
笔记:
您可以添加
ORDER BY
子句以对返回的行进行排序(如果需要)。外部查询上的
WHERE
子句可能是多余的,并且不必要。我们更喜欢避免使用
SELECT *
,而是更明确地列出要返回的表达式。关于mysql - 基于加入结果的订单选择(发送最后一条消息时的排序对话),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37930515/