2012-04-25 54 views
2

我删除了我以前的问题,使其更易于理解。 我开发这个数据库模式的一个论坛:MySQL难以查询

ID:INT->PRIMARY-KEY->AUTO_INCREMENT 
IDTOPIC:INT (0 if it is the "father" topic OR father's ID if it's a reply) 
IDUSER:INT (ID of user who posted) 
CONTENT:MEDIUMTEXT 
DATE:TIMESTAMP 

我需要按日期,下令查询哪里得到的只有最后一个线程的答复(如果没有“我是谁回答的最后一个用户”,ID用户<> $ userid)或父主题主题(如果没有回复)。 即使主题或答复的结果,我需要打印的第一线IDTOPIC/ID用户

我理想的结果应该是这样的:

ID:IDTOPIC:IDUSER:CONTENT:DATE:IDLASTREPLY:IDLASTUSERREPLY:LASTCONTENTREPLY:LASTDATEREPLY 

存在,如果最后四个字段都为NULL没有问题。 我需要尽可能快的查询。 请帮帮我!

+0

你存储帖子使用“邻接列表”,这可能不是您数据的最佳结构。您应该研究在数据库中存储分层数据的替代方法。 [这个问题](http://stackoverflow.com/questions/192220/what-is-the-most-efficient-elegant-way-to-parse-a-flat-table-into-a-tree)是一个很好的开始。 – eggyal 2012-04-25 17:19:16

+0

但我的论坛方式与其他一些“知名”产品完全一样,例如joomla/phpBB ......他们都使用一张带有IDTOPIC或PARENT字段的表格来分割话题...... – 2012-04-25 18:38:56

回答

1
SELECT fa.ID, fa.IDTOPIC, fa.IDUSER, fa.CONTENT, fa.DATE, 
    re.ID as IDLASTREPLY, 
    re.IDUSER as IDLASTUSERREPLY, 
    re.CONTENT as LASTCONTENTREPLY, 
    re.DATE as LASTDATEREPLY, 
    CASE WHEN (re.DATE is NULL) THEN fa.DATE ELSE re.DATE END as LASTUPDATE 
FROM post fa 
    LEFT JOIN post re ON re.ID = 
    (SELECT ID FROM post WHERE IDTOPIC = fa.ID ORDER BY DATE DESC LIMIT 1) 
WHERE fa.IDTOPIC = 0 
ORDER BY LASTUPDATE DESC 

和订单,只要你喜欢。
但它不是很好的表现。我认为你可以改善你的表格结构。

编辑:添加LASTUPDATE为ORDER

+0

谢谢,但通过这种方式,我无法订购,因为在没有答复的情况下,re.DATE为空,那将是显示的第一条记录。 – 2012-04-25 18:27:57

+1

好吧,我编辑我的代码,添加LASTUPDATE列。怎么样? – tosin 2012-04-25 19:19:32

+0

不,因为正确的顺序是:CASE WHEN(re.DATE为NULL)然后fa.DATE ELSE re.DATE END为LASTUPDATE – 2012-04-25 22:18:41

0

不幸的是,这个选择是不是有些帖子经过这么好...... 今天,总表上的约900条记录,当我通过过滤线程我用户ID(只有45个不同的线程!),MySQL需要0.30秒(在开始时,只需要0.04/0.05秒...我认为恶化与我订阅的线程数成正比) 这可能意味着当我将有300个不同的线程订阅我应该等待大约2秒这个查询...它太多了。 奇怪的是,如果我“限制0,10”这个查询或获得完整查询,执行速度不会改变!这就是为什么我认为这不好...因为我想即使我限制,它也必须选择整个数据。 没办法解决。这是我如何设置查询。有一个新的notications表,因为我想用它作为通知查询(展现唯一的回答不是$ USERID制造)

NOTIFICATIONS表中的字段:ID,idcontent,用户ID

SELECT 
    CASE WHEN (re.id is NULL) THEN fa.id ELSE re.id END AS id, 
    fa.id as idtopic, 
    CASE WHEN (re.userid is NULL) THEN fa.userid ELSE re.userid END AS userid, 
    CASE WHEN (re.content is NULL) THEN fa.content ELSE re.content END AS content, 
    n.notify, 
    u.id as reuserid, u.name, u.surname, u.photo, 
    CASE WHEN (re.date is NULL) THEN unix_timestamp(fa.date) ELSE unix_timestamp(re.date) END AS LASTUPDATE 
FROM notifications AS n 
LEFT JOIN post AS fa 
    ON fa.id = n.idcontent 
LEFT JOIN post AS re 
    ON re.id=(SELECT ID FROM post WHERE IDTOPIC = fa.ID AND userid <> $USERID ORDER BY DATE DESC LIMIT 1) 
LEFT JOIN users AS u 
    ON u.id = (CASE WHEN (re.userid is NULL) THEN fa.userid ELSE re.userid END) 
WHERE 
    n.userid = $USERID 
    AND NOT (fa.userid = $USERID AND re.userid = $USERID)