我可以想到两种“正确”的方式来做到这一点。第一个是使用连接和子查询:
SELECT f.id AS forum_id,
f.name AS forum_name,
t.id AS thread_id,
t.topic AS thread_topic,
t.ts AS thread_timestamp,
p.id AS post_id,
p.content AS post_content,
p.ts AS post_timestamp
FROM forums f join
threads t
on f.id = t.forum_id join
posts p
on t.id = p.thread_id
WHERE t.ts = (select ts from threads t2 where t2.forum_id = t.forum_id order by ts desc limit 1) and
p.ts = (select ts from posts p2 where p2.thread_id = p.thread_id order by ts desc limit 1)
GROUP BY f.id
ORDER BY max(p.ts)
这种方法的问题在于,这会返回最新的线程和该线程上的最新帖子。解决这个问题很麻烦(这可能是你真正想要的。)
子查询获取 和 的最新threads
日期posts
。性能取决于您拥有的索引。这可能是可以接受的。这是标准 SQL。
另一个是substring_index()
/的技巧group_concat()
,这是 MySQL 特有的:
SELECT f.id AS forum_id,
f.name AS forum_name,
substring_index(group_concat(t.id order by t.ts desc separator '|'), '|', 1) AS thread_id,
substring_index(group_concat(t.topic order by t.ts desc separator '|'), '|', 1) AS thread_topic,
substring_index(group_concat(t.ts order by p.ts desc separator '|'), '|', 1) AS thread_timestamp,
substring_index(group_concat(p.id order by p.ts desc separator '|'), '|', 1) AS post_id,
substring_index(group_concat(p.content order by p.ts desc separator '|'), '|', 1) AS post_content,
substring_index(group_concat(p.ts order by p.ts desc separator '|'), '|', 1) AS post_timestamp
FROM forums f join
threads t
on f.id = t.forum_id join
posts p
on t.id = p.thread_id
GROUP BY f.id
ORDER BY max(p.ts);
此版本的性能可能会更好(因为您已经承担了 a 的开销group by
)。必须选择分隔符,因此它不在任何值中。否则,只会出现分隔符之前的部分。
一个优点是线程和帖子是独立处理的,因此您可以获得最新的线程,并且分别获得最新的帖子。您可以通过更改order by
.group_concat()
此外,要获得您想要的订购,您需要订购max(p.ts)
而不是仅订购p.ts
. 后者将通过论坛上的任意时间戳进行排序;不能保证它会是最新的。