2013-06-02 42 views
1

我正在構建一個簡單的論壇。我需要展示的是帶有最新主題的列表,並且在每個主題附近都有最新的回覆/帖子。例如:不返回所有行與左連接和HAVING

Topic name:   | Last reply: 
Topic name 1 here | 2013-02-01 by username1 
Topic name 2 here | 2013-01-01 by username2 
etc. 

問題是主題和回覆都在同一個表中,稱爲「網頁」。 該表格有一個字段模板,當然包含表格'模板'的ID。

所以我乾脆加入模板和過濾器由Template.name備案「論壇」

這將返回所有主題。因爲我還需要針對每個主題的最新回覆,所以我決定在同一模板上使用過濾器進行子查詢,但現在記錄爲「論壇回覆」,並由Reply.date DESC和LIMIT 1進行排序,並返回最新回覆這個話題。現在是時候顯示我這對於含有至少1篇回覆主題正常工作電流查詢:

/*----some fields to return----*/ 
SELECT TopicContent.title, ReplyContent.title, Reply.date, Reply.id, 
(
    /*----subquery to return latest reply id used inside HAVING later on----*/ 
    SELECT Reply.id 
    FROM pages AS Reply 
    INNER JOIN templates AS Template ON Reply.template = Template.id 
    WHERE Reply.parent_id = Topic.id 
    AND Template.name = 'Forum reply' 
    ORDER BY Reply.date DESC 
    LIMIT 1 
) AS reply_id 
FROM pages AS Topic 
INNER JOIN templates AS Template ON Topic.template = Template.id 
INNER JOIN page_content AS TopicContent ON Topic.id = TopicContent.page 
/*----left join used because topic could have zero replies if new----*/ 
LEFT JOIN pages AS Reply ON Topic.id = Reply.parent_id 
LEFT JOIN page_content AS ReplyContent ON Reply.id = ReplyContent.page 
WHERE Template.name = 'Forum topic' 
HAVING Reply.id = reply_id 
/*--------------------------------------------------------------------------------*/ 
/*----HAVING   | returns not all topics but with correct latest reply----*/ 
/*----GROUP BY Topic.id | returns topics correctly but incorrect latest reply-----*/ 

現在最重要的是,如果一個新的話題提交它不包含任何回覆呢。

所以,當我使用HAVING它只返回也包含至少一個答覆的主題。 而使用GROUP BY時,它不會返回包含一個或多個回覆的主題的最新回覆。而對於不包含回覆的主題,它返回NULL,這是很好的。

我需要更改JOINS嗎?任何想法來解決這個問題。非常感謝!

回答

1

我想將MaxId子查詢移動到from子句中,因爲您使用GROUP BY的方式對於您嘗試執行的操作不起作用。在這裏,您只需將您的結果集加入到檢索MaxId字段的子查詢中。

SELECT 
* 
FROM 
    pages 
    . 
    . 
    . 
    LEFT OUTER JOIN 
    (
    SELECT 
     ReplyId As [MaxId], 
     p.Template 
    FROM 
     Pages p INNER JOIN Templates t ON p.Template = t.Id 
    WHERE 
     TemplateName = 'Forum Reply' 
    ORDER BY ReplyDate LIMIT 1 
    ) a ON a.Template = pages.Template 
WHERE 
    Template.name = 'Forum topic' 

或者(這個可以給你一個以上的迴應,如果多個第一篇在這種情況下,你可能會限制的結果完全一樣的時間)

SELECT 
    * 
FROM 
    pages 
    . 
    . 
    . 
    (SELECT 
     ReplyId As [MaxiId], 
     Template 
    FROM 
     Pages p INNER JOIN 
     Templates t ON p.Template = t.id LEFT OUTER JOIN 
     (SELECT 
     p.Template, 
     MIN(ReplyDate) AS [FirstReplyDate] 
     FROM  
     Pages p INNER JOIN 
     Templates t ON p.Template = t.id 
     WHERE 
     TemplateName = 'Forum Reply' 
     GROUP BY 
     p.Template) b ON b.Template = t.id 
    WHERE 
     p.ReplyDate = b.FirstReplyDate 
    ) a ON a.Template = pages.Template 

無論哪種方式,你應該移動該首先回答子查詢From子句

+0

謝謝你的回答。你能解釋爲什麼你加入a.TemplateId = pages.TemplateId。我試圖找出/解決它,但似乎沒有工作。 –

+0

這可能是因爲我不太瞭解你的數據結構,但是在你的子查詢中你將頁表加入到這一列的模板表中(我將編輯它以使用你使用過的相同名稱)。以上應該給你一個通用的解決方案。 – Rick

+0

你好,英格蘭人。謝謝你的幫助。雖然它沒有工作。我認爲這是不可能的。不符合我們的方式。這就是爲什麼我決定從pages表格中提出主題和回覆的原因。我現在正在製作表格主題和答覆,並更改我的腳本。這種方式當然是最好的,現在我沒有在我的網頁表上有空的字段annymore,這也很棒。只是想知道它是否可以完成。 –

0

這還不是答案,而是要求從海報中獲得更多信息,但因爲評論太長,我會在這裏發帖。

從您的查詢,我可以斷定,你的表是這個樣子

templates(id, name) 
pages(id, parent_id, date, template) 
page_contents(page, title) 

pages存儲後的結構,該職位的page_contents存儲內容,並template確定哪些類型的訊息。我對麼?

問:

  • 什麼是PARENT_ID的價值,如果它是話題,而不是一個答覆。由於答覆屬於主題,所以parent_id應該是主題的ID。但是,主題不在任何主題下,所以基本上它應該是0或NULL,是不是?
  • 您是否僅限於此數據庫設計,從我的角度來看,此數據庫設計不適合論壇,因爲要檢索這樣簡單的內容,您必須INNER JOIN一堆表格。
+0

您對我的表的外觀如何正確。主題parent_id有一個父頁面,在這種情況下是'新聞和信息'。這是一個包含模板「論壇組」的父頁面。論壇組的母公司是'論壇'。所以主題parent_id值永遠不會是0.不,我不受限制。我建立了自己的結構,因爲我認爲在建立多語言網站時它會很方便。這個將存儲在page_content中。我可以隨心所欲地做我想做的事情,所以我可以製作額外的表格,稱爲'主題'和'回覆',但我不會如果可能的話就不會。感謝您現在快速回復。 –