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

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以及以某种方式JOINposts感兴趣,以便在单个查询(没有子查询)中获得每个线程的第一篇和最后一篇文章。到目前为止,我可以使用多个查询来做到这一点,并且我将第一篇文章定义为:

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


但是当然我不能一次得到两个,因为我需要同时对ASCDESC进行排序。
这里有什么解决方案?甚至可以使用一个查询吗?有什么办法可以更改表的结构来简化此操作?如果这样做不可行,那么在这种特殊情况下,您可以给我什么提示来提高查询性能?

最佳答案

您可以使用子查询并加入以下内容:

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个新列,以包含第一篇和最后一篇文章的那些数据。它复制了数据,但是这意味着您可能可以显示线程列表,而根本不需要查询posts表。

关于mysql - 获取主题中的第一篇和最后一篇文章,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12231424/

10-15 18:29