需要有关 SQL 请求的反馈(MySQL、GROUP BY 行为)
我正在编写一个私人对话系统,需要针对我最复杂的请求提供建议。
我的(简化的)表,在 MySQL 5.5 下:
user:
id (int)
username (string)
conversation:
id (int)
subject (string)
conversation_user:
conversation_id (int)
user_id (int)
message:
id (int)
conversation_id (int)
user_id (int)
content (text)
created_at (datetime)
所以,我想向用户显示他正在参与的对话列表:对于每个对话,我需要对话 id、对话主题、参与用户列表,最后一条消息 ID、最后一条消息作者 ID 和用户名以及最后一条消息日期。
我写了这个请求,看起来很糟糕:
SELECT
cu.conversation_id,
c.subject,
u.username,
m.id,
m.user_id,
m.created_at
FROM conversation_user cu
JOIN conversation c ON c.id = cu.conversation_id
JOIN conversation_user cu2 ON cu2.conversation_id = c.conversation_id
JOIN user u ON u.id = cu2.user_id
JOIN message m ON m.conversation_id = cu.conversation_id
WHERE cu.user_id = :current_user_id # the session user_id
AND m.id = (SELECT MAX(id) FROM message WHERE conversation_id = cu.conversation_id)
所以,我想知道你们是否有更好的方法来获得相同的结果?
我已经阅读了 GROUP当 SELECT 子句中不存在聚合函数时,BY 行为,这就是为什么我没有放置 GROUP BY 子句而是写了最后一行: AND m.id = (SELECT MAX(id) FROM message WHERE conversation_id = cu.conversation_id)
谢谢!
编辑
我对此请求进行了解释,并且没有用于 JOIN user u ON u.id = cu2.user_id
行的 KEY:为什么?
(第一个问题仍然相关)
I'm programming a private conversation system and need advices on my most complex request.
My (simplified) tables, under MySQL 5.5 :
user:
id (int)
username (string)
conversation:
id (int)
subject (string)
conversation_user:
conversation_id (int)
user_id (int)
message:
id (int)
conversation_id (int)
user_id (int)
content (text)
created_at (datetime)
So, I want to display to the user the list of the conversations in which he is participating : for each conversation, I need the conversation id, the conversation subject, the list of participating users, the last message id, the last message author id and username, and the last message date.
I've written this request, which looks pretty bad :
SELECT
cu.conversation_id,
c.subject,
u.username,
m.id,
m.user_id,
m.created_at
FROM conversation_user cu
JOIN conversation c ON c.id = cu.conversation_id
JOIN conversation_user cu2 ON cu2.conversation_id = c.conversation_id
JOIN user u ON u.id = cu2.user_id
JOIN message m ON m.conversation_id = cu.conversation_id
WHERE cu.user_id = :current_user_id # the session user_id
AND m.id = (SELECT MAX(id) FROM message WHERE conversation_id = cu.conversation_id)
So, I would like to know if you guys see a better way to get the same result ?
I've already read GROUP BY behavior when no aggregate functions are present in the SELECT clause, that's why I didn't put a GROUP BY clause and wrote the last line instead :AND m.id = (SELECT MAX(id) FROM message WHERE conversation_id = cu.conversation_id)
Thanks !
Edit
I did an EXPLAIN on this request, and there is no KEY used for the JOIN user u ON u.id = cu2.user_id
line : why ?
(the first question is still relevant)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
还有其他选择,就像我即将为您提出的那样。但是,老实说,我就是这样做的:)
上面的内容允许您按日期或其他字段进行排序,并且仍然只选择一个消息 ID。
上面避免了相关子查询,因此可以(但并不总是)更快。
就没有用于
JOIN user u ON u.id = cu2.user_id
的密钥而言,相关的两个表都都有索引吗相关领域?There are alternatives, such as I'm about to put forward for you. But, honestly, that's how I'd do it :)
The above allows you to order by DATE or somet other field, and still pick just one message id.
The above avoids a correlated sub-query, and so can (but not always) be faster.
In terms of there be no key being used for
JOIN user u ON u.id = cu2.user_id
, do both of the two tables in question have indexes on the relevant fields?