7

SQLFiddle リンク

たくさんのテスト/試験問題を含む SQLite データベースを持っています。各質問は、1 つの質問カテゴリに属します。

私のテーブルは次のようになります。
so_questions テーブル

目標
私がやろうとしているのは、5 つのランダムな質問を選択することですが、結果には各カテゴリから少なくとも1 つが含まれている必要があります。目標は、各カテゴリから質問をランダムに選択することです。

たとえば、出力は質問 ID1, 2, 5, 7, 8または2, 3, 6, 7, 8またはになり8, 6, 3, 1, 7ます。

ORDER BY category_id, RANDOM()
以下の SQL を実行すると、SQLite から質問のランダムなリストを取得できますが、結果に各カテゴリの質問が含まれていることを確認するにはどうすればよいですか?

SELECT ORDER BY category_id、ランダム

基本的に、私はこのようなもの、SQLite バージョンを探しています。

5 つの結果のみを取得したいのですが、各カテゴリから 1 つ (または複数) を取得し、すべてのカテゴリが結果セットに表示されます。

報奨
金 SQLite だけでこれを達成できるかどうか興味があるので、報奨金を追加しました。SQLite + Java で実行できますが、SQLite のみでこれを実行する方法はありますか? :)

SQLFiddle リンク

4

3 に答える 3

6

答えの鍵は、結果に 2 種類の質問があることです。カテゴリごとに、そのカテゴリから来るように制約する必要がある 1 つの質問。そしていくつかの残りの質問。

まず、制約付きの質問: 各カテゴリから 1 つのレコードを選択するだけです。

SELECT id, category_id, question_text, 1 AS constrained, max(random()) AS r
FROM so_questions
GROUP BY category_id

(このクエリは、SQLite 3.7.11 (Jelly Bean 以降) で導入された機能に依存しています。クエリSELECT a, max(b)では、 の値aは、最大b値を持つレコードから取得されることが保証されています。)

制約のない質問も取得する必要があります (制約のあるセットに既に含まれている重複を除外することは、次のステップで行われます)。

SELECT id, category_id, question_text, 0 AS constrained, random() AS r
FROM so_questions

これら 2 つのクエリを で結合しUNION、 でグループ化するとid、すべての重複がまとめられます。次に選択max(constrained)すると、重複するグループに対して、制約付きの質問のみが残ります (他のすべての質問は、とにかくグループごとに 1 つのレコードしかありません)。

最後に、ORDER BY節により、制約付きの質問が最初に来て、その後に他のランダムな質問が続くことが保証されます。

SELECT *, max(constrained)
FROM (SELECT id, category_id, question_text, 1 AS constrained, max(random()) AS r
      FROM so_questions
      GROUP BY category_id
      UNION ALL
      SELECT id, category_id, question_text, 0 AS constrained, random() AS r
      FROM so_questions)
GROUP BY id
ORDER BY constrained DESC, r
LIMIT 5

以前の SQLite/Android バージョンでは、一時テーブルを使用せずに解決策を見つけられませんでした (制約付きの質問のサブクエリを複数回使用する必要がありますが、random().

BEGIN TRANSACTION;

CREATE TEMPORARY TABLE constrained AS
SELECT (SELECT id
        FROM so_questions
        WHERE category_id = cats.category_id
        ORDER BY random()
        LIMIT 1) AS id
FROM (SELECT DISTINCT category_id
      FROM so_questions) AS cats;

SELECT ids.id, category_id, question_text
FROM (SELECT id
      FROM (SELECT id, 1 AS c
            FROM constrained
            UNION ALL
            SELECT id, 0 AS c
            FROM so_questions
            WHERE id NOT IN (SELECT id FROM constrained))
      ORDER BY c DESC, random()
      LIMIT 5) AS ids
JOIN so_questions ON ids.id = so_questions.id;

DROP TABLE constrained;
COMMIT TRANSACTION;
于 2012-10-16T21:01:25.923 に答える
4

基本的にあなたが探しているのはselect top N max valuesです。朝の3~4時間かけて探します。(まだ成功していません。あと数時間待つ必要があるかもしれません)。

一時的な解決策として、次のようにgroup byオプションを使用できます。

String strQuery = "SELECT * FROM so_questions group by category_id;";

出力は次のとおりです。

ここに画像の説明を入力

正確なあなたの条件で戻ってきます。

于 2012-09-20T16:06:40.180 に答える
2

それはsqliteなので(したがってローカル):5つの回答と4つの異なるカテゴリが得られるまでクエリを実行すると、反復ごとに重複するカテゴリ行が削除されるのがどれほど遅くなりますか。

各カテゴリが同等に表現されている場合、1 秒未満である必要がある 3 回以上の反復が必要になる可能性はほとんどないと思います。

アルゴリズム的には良くありませんが、SQL ステートメントで random() を使用することは、とにかくアルゴリズム的には良くありません。

于 2012-09-21T07:06:22.387 に答える