0

SOとは異なり、QAサイトを作成しています。データベースにあるすべての質問を一覧表示し、各質問の投票数と回答数をカウントして、特定のユーザーが各質問にすでに投票しているかどうかを確認したいと思います。同じクエリで。

バックアップして、少しコンテキストを説明しましょう。私は次のSQLテーブルを持っています:

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

1つ目は質問の表で、数値ID、タイトル、およびテキストが含まれています。ユーザーは質問に投票できます。賛成票のみがあります。各ユーザーは、好きなだけ質問に投票できますが、質問ごとに1回だけ投票できます。ユーザーが質問に投票するたびに、エントリがvotesテーブルに追加され、quesitonidとuseridが記録されます。回答テーブルには、各回答の数値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

さて、これまでのところとても良いです。ここで、これら2つのテーブルを結合したいので、qidで結合するだけです。

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 に答える