0

大規模な質問プールから抽出された質問の組み合わせで構成されるテストを生成するプログラムを作成しました。各テストにはいくつかの基準があり、プログラムはこれらの基準を満たした場合にのみそれらをデータベースに保存しました。

私のプログラムは、質問ができるだけ均等に分散されるように作成されています。つまり、質問の組み合わせを生成するとき、アルゴリズムは、以前の反復で最も少ない回数質問された質問をプールから優先順位付けします。

test_questions基本的にtest_idfor each テストを格納するテーブルを 1 つ作成し、テストごとにn 行 (n は各テストの質問数) を使用して s とそれに対応するtest_questionsを格納するテーブルを作成しました。test_idquestion_id

テストがデータベースに保存されたので、テストの異なるペア間の質問の重複が特定の範囲内にあることを確認したいと思います.SQLを使用してこれを行うことができるはずだと思いました.

自己結合を使用して、このクエリを使用して、テスト 3 とテスト 5 に共通する質問を選択することができました。

-- Get the number of questions that are common to tests 3 and 5
SELECT count(tq1.question_id) AS Overlap
FROM test_questions AS tq1
JOIN test_questions AS tq2
ON tq1.question_id = tq2.question_id
WHERE tq1.test_id = 5
AND tq2.test_id = 3;

最初の n (5) 個のテストから、可能なテスト ペアの各組み合わせを生成することができました。

-- Get all combinations of pairs of tests from 1 to 5
SELECT t1.test_id AS Test1, t2.test_id AS Test2
FROM tests AS t1
JOIN tests AS t2
ON t2.test_id > t1.test_id
WHERE t1.test_id <= 5
AND t2.test_id <= 5;

私がやりたいことは、上記の 2 つのクエリを組み合わせて、最初の 5 つのテストの可能なペアの組み合わせを、両方のテストに共通する質問の数とともに表示することです。

-- This doesn't work
SELECT t1.test_id AS Test1, t2.test_id AS Test2, count(tq1.question_id) AS Overlap
FROM tests AS t1
JOIN tests AS t2
ON t2.test_id > t1.test_id
JOIN test_questions AS tq1
ON t1.test_id = tq1.test_id
JOIN test_questions AS tq2
ON t2.test_id = tq2.test_id
WHERE t1.test_id <= 11
AND t2.test_id <= 11
GROUP BY t1.test_id, t2.test_id;

このSQL Fiddleで 2 つのテーブルの単純化されたバージョン (ランダム化されたデータを使用) を作成しました

注: DBMS として MySQL を使用していますが、SQL は ANSI 標準と互換性がある必要があります。

編集:テストを生成するために書いたプログラムは、実際には必要な数よりも多くのテストを生成しました。最初の n 個のテストのみを比較したいと思います。この例では<= 5、余分なテストを無視するために WHERE 条件を追加しました。

Thorsten Kettner のサンプル データに従って、私が探しているものを明確にするには:

test 1: a, b and c
test 2: a, b and d
test 3: d, e and f

結果は次のようになります。

Test    Test    Overlap
Test1   Test2   2       (a and b in common)
Test1   Test3   0       (no questions in common)
Test2   Test3   1       (d is common to both)
4

3 に答える 3

4

group by最初のクエリに必要なのは(基本的に)だけです。別の条件も追加したため、テスト ID が順番に生成されます。

SELECT tq1.test_id as test_id1, tq2.test_id as test_id2, count(tq1.question_id) AS Overlap
FROM test_questions tq1 LEFT JOIN
     test_questions tq2
     ON tq1.question_id = tq2.question_id and
        tq1.test_id < tq2.test_id
GROUP BY tq1.test_id, tq2.test_id;

これは標準 SQL です。

共通の質問がないものも含め、すべてのペアのテストを取得したい場合は、別の方法を次に示します。

SELECT t1.test_id as test_id1, t2.test_id as test_id2, count(tq2.question_id) AS Overlap
FROM tests t1 CROSS JOIN
     tests t2 LEFT JOIN
     test_questions tq1
     on t1.test_id = tq1.test_id LEFT JOIN
     test_questions tq2
     ON t2.test_id = tq2.test_id and tq1.question_id = tq2.question_id 
GROUP BY t1.test_id, t2.test_id;

これは、テストごとに 1 行のテーブルがあることを前提としています。そうでない場合は、 に置き換えtestsます(select distinct test from test_questions)

于 2014-03-21T11:37:36.867 に答える
2

私はゴードンの答えを修正しました。このクエリは、テストの組み合わせのリストと、それに対応する重複 (共通の質問) を提供します。

SELECT tq1.test_id as test_id1, tq2.test_id as test_id2, count(tq1.question_id) AS Overlap
FROM test_questions tq1
JOIN test_questions tq2
ON tq1.question_id = tq2.question_id
AND tq1.test_id < tq2.test_id 
WHERE tq1.test_id <= 5
AND tq2.test_id <= 5
GROUP BY tq1.test_id, tq2.test_id;
于 2014-03-21T12:32:08.203 に答える
1
  • 最初のステップ: すべてのテストの組み合わせを検索します。例: 1-2、1-3、2-3
  • 2 番目のステップ: 最初のテストのすべての問題に参加します。
  • 3 番目のステップ: 2 番目のテストの等しい問題が存在する場合は、外部結合します。
  • 最後のステップ: テストの組み合わせごとに見つかった同等の質問を数えます。
    select test_combinations.t1_test_id, test_combinations.t2_test_id, count(q2.question_id)
    から
    (
        t1_test_id として t1.test_id、t2_test_id として t2.test_id を選択します。
        from (test_id t1.test_id のテストから test_id を選択
    ) test_combinations
    内部結合 test_questions q1 on q1.test_id = test_combinations.t1_test_id
    q2.test_id = test_combinations.t2_test_id および q2.question_id = q1.question_id で test_questions q2 に参加しました
    test_combinations.t1_test_id、test_combinations.t2_test_id でグループ化
    test_combinations.t1_test_id、test_combinations.t2_test_id で並べ替えます。

フィドルに重複する質問のないテストを追加し、test_id <= 5 への制限を削除したので、重複する質問がないテストのペアが表示されます: http://sqlfiddle.com/#!2/e83aa/1

于 2014-03-21T12:37:42.123 に答える