2016-04-25 28 views
0

我想爲我的網站創建一個新聞源,顯示3種類型的信息:問題,答案(與問題相關)和討論。SQL - 多個聯接(新聞源)

我有一個稱爲活動的主表記錄了平臺的所有活動,併爲每種類型的記錄(用戶,問題解答和討論)的一個單獨的表,如下圖所示:

表活動

EventID EventType fkQuestionID fkAnswerID fkDiscussionID 
1  Question 1    NULL   NULL 
2  Question 2    NULL   NULL 
3  Discussion NULL   NULL   1 
4  Answer  1    1   NULL 
5  Question 3    NULL   NULL 
6  Discussion NULL   NULL   2 
7  Answer  2    2   NULL 
8  Discussion NULL   NULL   3 

表問題

QuestionID fkUserID QuestionTitle 
1   1   Who is Homer Simpson? 
2   2   What is the capital of Madagascar? 
3   3   What superpower would you choose? 

表問答

AnswerID fkQuestionID fkUserID Answer 
1   1    2   He is a characted of a... 
2   2    4   The capital is... 

圓桌討論

DiscussionID fkUserID DiscussionTitle 
1    3   The best day of my life 
2    1   The worst zombie movies 
3    2   The funiest scens of... 

表用戶

UserID Name 
1  Jack 
2  Ana 
3  Rose 
4  Brad 

這是預期的結果:

enter image description here

到目前爲止,我創建了以下查詢:

SELECT E.EventID, 
E.EventType, 
E.fkQuestionID, 
E.fkAnswerID, 
E.fkDiscussionID, 
Q.QuestionTitle, 
U1.Name as QuestionBy, 
A.Answer, 
U2.Name as AnswerBy, 
D.DiscussionTitle, 
U3.Name as PostBy 
FROM events E 
LEFT JOIN questions Q ON Q.QuestionID=E.fkQuestionID 
LEFT JOIN users U1 ON U1.UserID=Q.fkUserID 
LEFT JOIN (
SELECT fkQuestionID, MAX(AnswerID) AS AnswerID 
FROM answers 
GROUP BY fkQuestionID 
) t ON t.fkQuestionID = E.fkQuestionID //show the last answer 
LEFT JOIN answers A ON A.pkAnswerID = t.AnswerID 
LEFT JOIN users U2 ON U2.UserID=A.fkUserID 
LEFT JOIN dicussions D ON D.DiscussionID=E.fkDiscussionID 
LEFT JOIN users U3 ON U3.UserID=D.fkUserID 

鑑於表事件將存儲大量行的,我在懷疑一些事情,也關於慢的性能:

  • 當前查詢已經採取+ 2S工藝( 30行)。由於我正在製作一種新聞饋送頁面,而不是一次對所有數據進行大量查詢,因此我正在考慮使用一個循環並進行幾個單獨的查詢來爲每種類型的事件帶來其餘信息並使用ajax加載它(減少服務器響應並增加頁面加載的印象)。這是一個愚蠢的想法?

  • 對於與表用戶的連接,有沒有更好的方法,而不是對每種類型的事件使用許多左連接(U1,U2,U3)?我害怕在所有類型的事件中使用許多左連接。

  • 如果有人寫了一個新的答案,我試着只帶上與該問題有關的最後一個Answer(max AnswerID)。但是,我正在努力隱藏與同一問題相關的其他事件(以避免同一問題的重複供稿/事件)。有誰知道我該如何解決這個問題?

+0

請發佈純文本,而不是圖像,所以我們可以複製並粘貼到sqlfiddle。 – Barmar

+2

你不能寫條件連接。你通常所做的就是編寫多個查詢,每個查詢都與不同的表連接,並將它們與'UNION'結合起來。 – Barmar

+0

@Barmar:編輯爲純文本,tks! – czmarc

回答

1

我個人根本沒有看到事件表的理由。

我會通過A UNION ALL查詢解決這個問題,我會將問題和答案鏈接到查詢的同一行。例如:

SELECT 
'Question' as EventType, 
Q.QuestionID, 
t.AnswerID, 
NULL as DiscussionID, 
Q.QuestionTitle, 
U1.Name as QuestionBy, 
A.Answer, 
U2.Name as AnswerBy, 
NULL as DiscussionTitle, 
NULL as PostBy 
FROM questions Q 
JOIN users U1 ON U1.UserID=Q.fkUserID 
LEFT JOIN (
SELECT fkQuestionID, MAX(AnswerID) AS AnswerID 
FROM answers 
GROUP BY fkQuestionID 
) t ON t.fkQuestionID = Q.QuestionID 
LEFT JOIN answers A ON A.pkAnswerID = t.AnswerID 
LEFT JOIN users U2 ON U2.UserID=A.fkUserID 


UNION ALL 

SELECT 
'Discussion' as EventType, 
NULL, 
NULL, 
NULL, 
NULL, 
NULL, 
NULL, 
NULL, 
D.DiscussionTitle, 
U3.Name as PostBy 
FROM dicussions D 
LEFT JOIN users U3 ON U3.UserID=D.fkUserID 

當然,您可能想要限制某個用戶的where子句。如果你想要他們回答的問題以及他們提出的問題,那麼當你按用戶看時,再添加另一個UNION ALL。

在這一點上,你還應該檢查你的索引,以確保你在所有的連接字段上都有它們。

+0

不錯,使用UNION ALL(0.7s)可以更快地工作。但是,即使使用表答案的左加入,該查詢只會帶來已回答的問題。我怎樣才能適應也帶來未解答的問題? – czmarc

+0

並將EventType作爲問題(未回答)和答案 – czmarc

+1

不同,我使用另一個UNION與表問題一起解決並檢索未答覆的問題 – czmarc