SQL - 多个联接(新闻源)

时间:2016-04-25 22:27:26

标签: mysql sql join

我正在尝试为我的网站创建一个新闻Feed,其中显示了3种类型的信息:问题,答案(与问题相关)和讨论。

我有一个名为Events的主表,它记录了平台的所有活动,并为每种类型的记录(用户,问题,答案和讨论)提供了一个单独的表,如下所示:

表格事件

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

鉴于表Event将存储大量行,我对一些事情表示怀疑,同样关于性能缓慢:

  • 当前查询已处理+ 2秒(30行)。当我正在制作一种新闻Feed页面时,我不是一次性对所有数据进行大量查询,而是考虑使用循环并进行多个单独的查询来为每种类型的事件提供剩余信息并使用ajax加载它(减少服务器响应并增加页面加载的印象)。这是一个愚蠢的想法吗?

  • 对于与表Users的连接,是否有更好的方法,而不是为每种类型的事件使用多个LEFT JOINS(U1,U2,U3)?我害怕为所有类型的活动使用许多LEFT JOINS。

  • 如果有人写了一个新的答案,我试图只带上与该问题相关的最后一个答案(最大答案ID)。但是,我正在努力隐藏与同一问题相关的其他事件(为了避免同一问题的重复提要/事件)。有谁知道如何解决这个问题?

1 个答案:

答案 0 :(得分: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。

此时,您还应检查索引以确保在所有连接字段上都有它们。

相关问题