2009-07-27 20 views
0

これはよくある質問ですが、私はそれをどのように表現するのが適切かはわかりません。SQL:親とその子を選択

私は2つのテーブルがあります:私は質問のリストを取得したいと思いますと結果は次のように表示することができるように、彼らのは、回答

Questions { Id, Text... } 
Answers { Id, QuestionId, Text...} 

を:

  • 質問A
    • 質問に対する回答A
  • 質問B
    • B を疑問視する第一の答えを質問する
    • 第三の答えを質問する
    • 第二の答えは...など

ことが想定質問表の選択基準です。

非常に非効率的な方法は、すべての関連する質問を選択してから、それぞれのすべての回答を選択することです。別の非効率的な方法は、LEFT OUTER JOINを使用することです。

質問と回答を得る最も効率的で簡単な方法は何ですか? 1つのクエリで実行できますか?

+2

左外部結合は全く効率的ではありません。なぜあなたはそれを考えると思うか分からない。 – Shawn

+0

合意 - 下の私の答えを見てください。 JOINはこの正確な目的のためのものです。 – Christian

答えて

2

MySQL(MSSQLではありません)の場合は、次のようになります。

SELECT q.text, a.text 
FROM questions q 
LEFT JOIN answers a ON 
    q.quiestionid = q.id 
GROUP BY q.id, a.id 
ORDER BY q.id 

qがある場合は教えてください。

+0

MSSQLでうまくいくとは思わないのはなぜですか?あなたはANSI SQLを書きました。構文は、SQL Serverで正常に動作します。 – Eric

+1

afaikの場合、ANSI準拠のrdbmsでは、SELECT句の列をGROUP BY句にも表示する必要があります。 q.textとa.textはGROUP BY句に含める必要があります。 christianの例はPostgreSQLとMSSQLでは動作しません。上記を使用してpgとmssqlでのみ動作します:GROUP BY q.id、a.id、q.text、a.text –

+1

.idフィールドは主キーであり、繰り返されることはありません。無駄なグループをドロップ! –

1

なぜ、左結合が効率的ではないと思いますか?何度も答えられた質問については重複したデータが得られますが、これは配線上の余分なバイト数であり、心配はありません。

答えが返ってきましたが、mssql、sqliteなどの実際のSQLエンジンや、提案されているようにmysqlでうまく動作しますが、冗長です(プライマリキーにグループ化されていないため、とにかく複製されることはありません)。したがって、次の単純でタイプミス-修正版は、罰金と高速です:

SELECT q.id, q.text, a.id, a.text 
    FROM questions q 
    LEFT JOIN answers a ON a.questionid = q.id 
ORDER BY q.id 

あなたのクライアントコードは、単にあなたが望むよう「階層」グループと表示のものへ順番にするときq.id変化に気づく必要があります - どのように行うにはそれはあなたが使用するクライアント側の言語に依存します。たとえば、Pythonではitertools.groupbyを使用すると非常に簡単です(SQLサーバ側でグループを必要としませんが、クライアント側で必要ですかPythonのような言語で提供された機能を使ったり、自分で実装したりすることで、希望通りに階層を表示することができます。

+0

ええ、私は最悪の場合、20〜100件の回答があると仮定して、重複データに非効率性があると考えていました。シンプルさを考えれば、とにかく試してみて、性能をテストしたらさらに最適化を延期します。 – cbp

関連する問題