我正在尝试获取
为什么吗
我希望能够显示以下详细信息:
"The latest Answer of forum $forum_id was given on Question $thread_id. Here it is: $post_id"
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,
threads t,
posts p
WHERE f.id = t.forum_id
AND t.id = p.thread_id
GROUP BY f.id
ORDER BY p.ts
任何建议,如何更改SQL以尽可能多地获得想要的结果?我试图避免使用子查询,但我心胸开阔!
提前致谢!
答案 0 :(得分:3)
由于MySQL不支持窗口功能,所以我认为没有子查询就可以做任何事情:
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 (SELECT t2.forum_id, max(p2.ts) as ts
FROM posts p2
JOIN threads t2 ON p2.thread_id = t2.id
GROUP BY t2.forum_id) max_p ON f.id = max_p.forum_id
JOIN posts p ON max_p.ts = p.ts
JOIN threads t ON f.id = t.forum_id AND p.thread_id = t.id
ORDER BY p.ts
当然,缓存最新的结果可以让你这样做而不会调用MAX()的性能损失,但是如果使用正确的索引,这不应该是一个很大的问题......
<强>更新强>
包含没有帖子和没有线程的论坛的线程的最简洁方法是使用LEFT JOIN而不是INNER JOIN:
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
LEFT JOIN (SELECT t2.forum_id, max(COALESCE(p2.ts, t2.ts)) as ts, COUNT(p2.ts) as post_count
FROM threads t2
LEFT JOIN posts p2 ON p2.thread_id = t2.id
GROUP BY t2.forum_id) max_p ON f.id = max_p.forum_id
LEFT JOIN posts p ON max_p.ts = p.ts
LEFT JOIN threads t ON f.id = t.forum_id AND (max_p.post_count = 0 OR p.thread_id = t.id)
ORDER BY p.ts
答案 1 :(得分:1)
我可以想到两种“正确”的做法。第一种是使用连接和子查询:
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);
此版本可能表现更好(因为您已经承担了group by
的开销)。必须选择分隔符,因此它不在任何值中。否则,只会显示分隔符前面的部分。
一个优点是线程和帖子是独立处理的,因此您可以获得最新的帖子,另外还有最新的帖子。您可以通过更改order by
中的group_concat()
条件来获取给定主题上的最新帖子。
另外,要获得所需的订单,您需要按max(p.ts)
订购,而不仅仅是p.ts
。后者将在论坛上以任意时间戳排序;不能保证它会是最新的。