Mysql 根据加入结果选择订单(对上次发送的邮件进行对话排序)
我正在Hibernate中为消息传递组件创建SQL查询。我的想法是查询以获取用户的对话,按上次发送消息的日期排序 我有两张桌子:Mysql 根据加入结果选择订单(对上次发送的邮件进行对话排序),mysql,sql,hibernate,select,Mysql,Sql,Hibernate,Select,我正在Hibernate中为消息传递组件创建SQL查询。我的想法是查询以获取用户的对话,按上次发送消息的日期排序 我有两张桌子: 对话 消息 在我的select查询中,我正在尝试类似的操作,但在最后发送的消息上从未发生排序 String sql = "SELECT * FROM conversations " + "JOIN messages ON messages.conversation_id = conversations.id "+
对话
消息
在我的select查询中,我正在尝试类似的操作,但在最后发送的消息上从未发生排序
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";
该问题是由于对
GROUPBY
子句的行为进行了特定于MySQL的扩展。其他数据库将抛出一个错误。。。类似于选择列表中的on aggregate“。(如果在sql模式中只包含\u FULL\u GROUP\u BY,我们可以让MySQL抛出类似的错误。)
表达式messages.created
的问题在于引用了GROUP BY中不确定行中的值。ORDER BY操作发生在GROUP BY操作之后的处理中
要获取为每个组创建的“最新”,请使用聚合表达式MAX(messages.created)
从同一行中获取其他值要复杂一些
假设创建的在给定的对话id
组中是唯一的(或者,如果不能保证它不是唯一的,您可以为创建的返回多个具有相同值的行)
要获取为每个会话创建的最新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
您可以将其用作内联视图,以获取最新创建的的整行
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)
注:
您可以添加一个orderby
子句,以便按照需要对返回的行进行排序
外部查询中的WHERE
子句可能是多余的,不必要的
我们宁愿避免使用SELECT*
,而宁愿显式列出要返回的表达式。问题是由于对GROUP BY
子句的行为进行了特定于MySQL的扩展。其他数据库会抛出错误……类似于SELECT list中的“聚合”。(我们可以让MySQL抛出类似的错误,如果我们在sql模式中只包含完整的组。)
表达式messages.created
的问题在于引用了GROUP BY中不确定行中的值。ORDER BY操作发生在GROUP BY操作之后的处理中
要获取为每个组创建的“最新”,请使用聚合表达式MAX(messages.created)
从同一行中获取其他值要复杂一些
假设创建的在给定的对话id
组中是唯一的(或者,如果不能保证它不是唯一的,您可以为创建的返回多个具有相同值的行)
要获取为每个会话创建的最新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
您可以将其用作内联视图,以获取最新创建的的整行
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)
注:
您可以添加一个orderby
子句,以便按照需要对返回的行进行排序
外部查询中的WHERE
子句可能是多余的,不必要的
我们更愿意避免使用SELECT*
,而更愿意显式列出要返回的表达式。@scaisEdge-在MySQL中不正确。此外,不适用,因为*
正在选择推荐选择表中的所有列。*但仍然相同results@scaisEdge:该语句绝对不正确。SQL不允许您可以按不在选择列表中的表达式进行排序(可能某些数据库有这种非标准限制,但MySQL或Oracle肯定没有这种情况)为什么你要按对话进行分组?是不是每次对话只会收到一条消息?@spencer7593实际上这从t ORDER by c3中选择不同的c1,c2;
是非法的,在MySQL的wierdogroupby
中也是非法的,但是whatever@scaisEdge-在MySQL中不正确。此外,由于*正在选择推荐选择表中的所有列。*但仍然相同results@scaisEdge:该语句绝对不正确。SQL确实允许您按不在选择列表中的表达式排序。(某些数据库可能有此非标准限制,但MySQL或Oracle肯定没有。)为什么你要按对话进行分组?是不是每次对话只会收到一条消息?@spencer7593实际上,这从t ORDER by c3中选择不同的c1,c2;
是非法的,而且在MySQL的wierdogroup by
中也应该是非法的,但这可能是OP想要的,但他们可能刚刚得到了想要SELECT*FROM()t order by created
有趣的是,在创建日期加入的方式…将对此进行一次尝试。谢谢Spencer…这看起来像是我想要的need@ConradFrix:这可能是OP想要的。但通常像这样的问题,OP想要的是“最新的”每个对话都有一条消息,并且希望在分组之前应用ORDER BY。这不是SQL的工作方式。感谢Spencer,这确实是正确的答案。我通过几个小调整成功地实现了它。干杯!我投了更高的票,因为这可能是OP想要的,但他们可能只是想要SELECT*FROM()t order by created
有趣的是,在创建日期加入的方式…将对此进行一次尝试。谢谢Spencer…这看起来就是我想要的need@ConradFrix:这可能是OP想要的。但通常像这样的问题,OP想要的是“最新的”消息,并希望在分组之前应用ORDER BY。SQL不是这样工作的。谢谢Spencer,这确实是正确的答案。I h