2012-04-25 55 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)