0

我正在制作一个 QA 网站,与 SO 不同。我想列出我数据库中的所有问题,计算每个问题的投票数和答案数,然后找出特定用户是否已经为每个问题投票。在同一个查询中。

让我备份并提供一些背景信息。我有以下 SQL 表:

qa_questions => questionid    title    text
qa_votes => voteid    questionid    userid
qa_answers => answerid    text    questionid    userid

第一个是问题表,其中包含数字 ID、标题和文本。用户可以为问题投票。只有赞成票。每个用户可以为他喜欢的多个问题投票,但每个问题只能投票一次。每当用户为一个问题投票时,都会在表格中添加一个条目votes,记录 quesitonid 和 userid。answers 表存储每个答案的数字 id 和文本,还引用正在回答的问题和提交答案的用户。

要获得所有问题的列表,计算每个问题的投票数,并显示特定用户(例如用户 #1)是否为该问题投票,我会:

SELECT qa_questions.questionid AS qid, title, text, COUNT( voteid ) AS num_votes,
MAX(CASE WHEN qa_votes.userid=1 THEN 1 ELSE 0 END ) AS voted_for
FROM qa_questions
LEFT JOIN qa_votes ON qa_questions.questionid = qa_votes.questionid
GROUP BY qa_questions.questionid

这行得通。返回的示例:

qid    title            text                                                num_votes    voted_for
1      What is 2 + 2?   I want to know the answer to this math question!    2            1

voted_for列中的 1 代表TRUE,表示当前用户已投票支持该问题)。

通过这样做,我还可以找出每个问题有多少答案:

SELECT qa_questions.questionid AS qid, COUNT( answerid ) AS num_answers
FROM qa_questions
LEFT JOIN qa_answers ON qa_questions.questionid = qa_answers.questionid
GROUP BY qa_questions.questionid

返回:

qid  num_answers
1    1
2    2
3    0
4    3

好的,到目前为止一切顺利。现在我想把这两个表结合起来,所以我干脆对qid进行一个join:

SELECT t1.qid, title, TEXT, num_votes, voted_for, num_answers
FROM (
    SELECT qa_questions.questionid AS qid, title, text, COUNT( voteid ) AS num_votes,
    MAX(CASE WHEN qa_votes.userid=1 THEN 1 ELSE 0 END) AS voted_for
    FROM qa_questions
    LEFT JOIN qa_votes ON qa_questions.questionid = qa_votes.questionid
    GROUP BY qa_questions.questionid
) AS t1
JOIN (
    SELECT qa_questions.questionid AS qid, COUNT( answerid ) AS num_answers
    FROM qa_questions
    LEFT JOIN qa_answers ON qa_questions.questionid = qa_answers.questionid
    GROUP BY qa_questions.questionid
) AS t2
ON t1.qid = t2.qid

嗯……呸。这行得通,但我不禁觉得它比它需要的丑得多......有没有办法可以简化这个?

4

1 回答 1

1

您可以简单地“堆叠”这些连接......这将大大提高性能。

SELECT 
  qa_questions.questionid AS qid, 
  title, 
  text, 
  COUNT(DISTINCT voteid ) AS num_votes,
  MAX(CASE WHEN qa_votes.userid=1 THEN 1 ELSE 0 END) AS voted_for, 
  COUNT(DISTINCT answerid ) AS num_answers
FROM qa_questions
LEFT JOIN qa_votes ON qa_questions.questionid = qa_votes.questionid
LEFT JOIN qa_answers ON qa_questions.questionid = qa_answers.questionid
GROUP BY qa_questions.questionid
于 2012-07-06T03:29:14.357 回答