2012-09-01 48 views
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,并以某种方式JOINposts ing,这样我就可以在单个查询中获得每个线程的第一个和最后一个帖子(没有子查询)。到目前为止,我能够使用多个查询做到这一点,我已经定义了第一篇文章是幸福:

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排序同时。
这里有什么解决方案?甚至可以使用单个查询吗?有什么办法可以改变我的桌子的结构以促进这一点吗?如果这不可行,那么您可以给我什么提示以改善这种特定情况下的查询性能?

+2

您可以将这两者联合在一起,只要您将每个都放在'()'中,以便它的'ORDER BY'只适用于它自己。或者你可以加入一个子查询,这将是高性能的。 –

+0

我需要为_each_线程获取第一个和最后一个帖子,所以我不认为'UNION'会做到这一点。子查询可能会。我会等待并看到其他建议。 – Grampa

回答

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个新列以包含第一篇和最后一篇文章的数据。它复制数据,但这意味着您可以显示线程列表,而无需查询帖子表。

+0

我很抱歉接受这个答案太久了。我决定与解决方案一起为第一篇和最后一篇文章添加额外的列。尽管这意味着额外的写入(和存储空间),但性能增益足以证明它的合理性。谢谢! – Grampa

相关问题