我试图显示所有最后消息的列表,类似于当您查看所有消息时显示在Facebook上的消息(并显示最后消息和消息的消息)。
我的表格如下:
id | userid | fromuserid | touserid | message | time
1 | 1 | 1 | 2 | test1 | 1428882596
2 | 2 | 1 | 2 | test1 | 1428882596
3 | 2 | 2 | 1 | test2 | 1428882600
4 | 1 | 2 | 1 | test2 | 1428882600
userid在那里是因为邮件是重复的(每个用户都有他/她自己的邮件副本,所以他们可以删除它们,也因为它们可以存储的最大邮件数限制。)
这是我的疑问:
SELECT messages.*
, users.username
, users.firstname
, users.lastname
FROM messages
LEFT JOIN users ON ( users.id = messages.fromuserid
AND messages.touserid = '$userid' )
OR ( users.id = messages.touserid
AND messages.fromuserid = '$userid' )
WHERE messages.id IN ( SELECT MAX(id)
FROM messages
WHERE userid = '$userid'
GROUP BY GREATEST(fromuserid, touserid)
, LEAST(fromuserid, touserid) )
ORDER BY messages.time DESC
查询有效,但速度非常慢(执行时间约为0.1 - 0.2秒,表格大约有8000个条目)。我也设置了索引,只是查询速度很慢。
有没有人知道更好的方法来做到这一点,而无需创建额外的表来存储最后的消息?无论我尝试了多少,我总是最终想到我需要创建一个额外的表,如果可能的话我想避免使用。
编辑:我知道文本复制是一个坏主意(我将为此创建一个单独的表),我的问题只是分组和显示最后的消息,如果可以在没有额外的表的情况下完成
非常感谢!
答案 0 :(得分:2)
如果您关心性能,有时最好使用flag
处理复杂查询(我们在表中添加了额外的列)
1-在消息表中添加一列,将其命名为isLast
,将默认值设为1
2-创建一个触发器before insert
到更新消息中属于当前用户的每一个旧行(我假设您可以使用NEW.touserid或NEW.fromuserid获取它), SET isLast = 0
3 - 然后在与用户加入消息时,您只需要在条件中检查isLast > 0
(不再有子查询)
答案 1 :(得分:0)
你想要尽可能多的表(在合理范围内)。
第一条规则,关联,不要复制!
如果可以,也会为列编制索引。
CREATE FULLTEXT INDEX idx ON `messages`(`message`);
在基于文本的列(CHAR,VARCHAR或TEXT列)上创建FULLTEXT索引,以帮助加快对这些列中包含的数据的查询和DML操作,省略任何定义为停用词的单词。
FULLTEXT索引定义为CREATE TABLE语句的一部分,或使用ALTER TABLE或CREATE INDEX添加到现有表中。
https://www.ntu.edu.sg/home/ehchua/programming/sql/Relational_Database_Design.html