0

我正在尝试编写一个论坛网站,我想显示一个线程列表。每个线程都应附有关于第一个帖子(线程的“头部”)以及最后一个帖子的信息。我当前的数据库结构如下:

threads table:
id   - int, PK, not NULL, auto-increment
name - varchar(255)

posts table:
id        - int, PK, not NULL, auto-increment
thread_id - FK for threads

这些表也有其他字段,但它们与查询无关。我有兴趣查询threads并以某种方式JOIN使用,posts以便在单个查询中获得每个线程的第一篇和最后一篇文章(没有子查询)。到目前为止,我可以使用多个查询来做到这一点,并且我将第一篇文章定义为:

SELECT *
FROM threads t
LEFT JOIN posts p ON t.id = p.thread_id
ORDER BY p.id
LIMIT 0, 1

最后一个帖子几乎相同,除了ORDER BY id DESC。现在,我可以通过执行以下操作选择多个线程及其第一篇最后一篇文章:

SELECT *
FROM threads t
LEFT JOIN posts p ON t.id = p.thread_id
ORDER BY p.id
GROUP BY t.id

但是我当然不能同时得到两者,因为我需要同时对两者进行ASC排序DESC
这里的解决方案是什么?甚至可以使用单个查询吗?有什么办法可以改变我的表格结构来促进这一点?如果这不可行,那么您能给我什么提示来提高这种特殊情况下的查询性能?

4

1 回答 1

1

您可以使用子查询和连接做一些事情:

SELECT first.text as first_post_text, last.text as last_post_text
FROM
  (SELECT MAX(id) as max_id, MIN(id) as min_id FROM posts WHERE thread_id = 1234) as sub
JOIN posts first ON (sub.max_id = first.id)
JOIN posts last ON (sub.min_id = last.id)

但这并不能解决您在没有子查询的情况下执行此操作的问题。

您可以在线程表中添加列,以便保留每个线程的第一个和最后一个帖子的 ID。第一篇文章永远不会改变,但是每次添加新文章时,您都必须更新线程表中的该记录,这样会使您的写入翻倍,并且您可能需要使用事务来避免竞争条件。

或者,您甚至可以在主题行中复制有关第一个和最后一个帖子的信息。假设您需要发布者的 user_id、发布的时间戳以及帖子的前 100 个字符。您可以在线程表中创建 6 个新列来包含第一篇和最后一篇文章的这些数据。它会复制数据,但这意味着您可以显示线程列表,而根本不需要查询帖子表。

于 2012-09-01T21:37:23.147 回答