1

テーブル question、topic、および question_has_topic (多対多の関係) があります。私のアプリケーションでは、管理者はトピックごとにグループ化された質問の内訳を見て、テストを作成するためにシステムにランダムに選択させたい質問をそれぞれからいくつ選択します。
これは彼らが見る種類のテーブルです:

+-------------------------------------+---------------------+--- ----------+
| | トピック | 利用可能な質問 | 選択: |
+-------------------------------------+---------------------+--- ----------+
| | 健康、安全、全般 | 13 | | |
| | 健康 | 3 | | |
| | 安全性 | 7 | | |
| | 一般 | 1 | | |
+-------------------------------------+---------------------+--- ----------+

カウントは、トピックの特定のグループに固有です。とにかく、彼らが選択したら、与えられたトピックのグループに対応する質問を選択する SQL ステートメントが必要です。つまり、健康、安全、一般に関する 3 つの質問が必要になる場合があります。
私はオンラインでいくつかの調査を行っていましたが、私がやろうとしていることは関係代数の除算として知られていると思います。ここでは、トピック ID の任意のグループ化の試みを示します。

question_has_topic から questionid を選択
存在しない場所 (
    question_has_topic から questionid を選択
    topicid が (8,9,10) に含まれていない場合)

結果は空ですが、データベースにはこれらすべてのトピック ID を持つ 2 つの質問があり、これが機能していないことがわかります。このリンクの例に従っていました

4

2 に答える 2

2

これはあなたが書き込もうとしていたことだと思いますが、それを行うには非常に非効率的な方法です-

SELECT questionid FROM question WHERE NOT EXISTS (
    SELECT topicid FROM topic WHERE topicid NOT IN (
        SELECT topicid FROM question_has_topic WHERE question.questionid = question_has_topic.questionid
    ) AND topicid IN (8, 9, 10)
);

これは間違いなくはるかに高速です-

SELECT *
FROM question_has_topic t1
INNER JOIN question_has_topic t2
    ON t1.questionid = t2.questionid AND t2.topicid = 9
INNER JOIN question_has_topic t3
    ON t2.questionid = t3.questionid AND t3.topicid = 10
WHERE t1.topicid = 8;

更新:もっと簡単な答えがあることはわかっていました。Cheranの方法ははるかに単純であり、INNERJOINよりもわずかに高速に実行されるはずです。彼の答えを受け入れてください。

于 2012-02-20T02:53:58.450 に答える
2

編集:質問を読み違えたため、古い投稿を削除しました。


これは、私が過去に使用したテクニックです。

  SELECT qht.questionid
    FROM question_has_topic AS qht
   WHERE qht.topicid IN (8,9,10)
GROUP BY qht.questionid
  HAVING COUNT(*) = 3 AND
         COUNT(*) = (SELECT COUNT(*) FROM question_has_topic AS dupe
                     WHERE dupe.questionid = qht.questionid)

ここ3で、特定のグループ内のトピックの数に対応します。これは、各(questionid, topicid)ペアquestion_has_topicが一意であることを前提としています (多対多の関係テーブルにある必要があります)。

このクエリが機能する方法は、最初に目的のトピックが少なくとも 1 つ割り当てられている質問を選択し ( WHERE qht.topicid IN (8,9,10))、次にquestionid. 最初の HAVING 句 ( COUNT(*) = 3) は、特定の質問に 3 つのトピックすべてが割り当てられている場合にのみ true になります (この表では重複が許可されていないと想定しているため)。2 番目の HAVING 句は、質問に割り当てられたトピックの総数をチェックします。これは、たとえば、質問にトピック 8、9、10、および 11 が割り当てられている可能性がある場合を防ぐためです。

于 2012-02-20T06:07:53.120 に答える