2011-12-26 3 views
4

を選択して私たちは、すべての質問が保存されている(QuestionBankという名前)のテーブルを持っている:すべてのパーティション内のレコードの指定した数のランダムパーティションのレコード

Id  Topic  Hardness Position 
4  1   3   4 
5  1   2   1 
6  1   1   2 
7  1   3   3 
8  1   3   4 
9  2   2   1 
10  2   2   2 
11  2   3   3 
12  3   1   1 
13  3   1   1 
14  3   1   2 

すべての質問には、トピックに属し、それは自身の硬さと位置だしました(その内容に基づいたすべての同様の質問は、対応するトピックで同じ位置にあります)。

[位置]列の値は無意味で、トピック内で同様の質問を区切ります。

目標は、ハーネス= 1のXレコードと硬度= 2のYレコードと硬度= ZのZレコードをランダムにN個選択することです。可能な限り同じようなトピックと位置を持つレコードが結果セットに返されるという制約があります。

たとえば、Id = 4とId = 8のレコードはトピックと位置が似ているため、そのうちの1つが結果セット内にあることが望まれます。

答えて

1

ここには1つの方法があります。

  1. 最初にTopic, Positionに複数の質問がある場合は、これらのそれぞれにランダムな順序番号RN1を割り当てます。
  2. 次に、それを各グループ内でランダムに並べ替えます。 RN11の値はすべて、特定のTopic, Positionコンボの2番目の質問を示す2に到達する前に、最初に注文されることは明らかです。
  3. Hardnessでパーティション化されたROW_NUMBER計算の結果を使用して、最終的にSELECTを簡単にします。

WITH T1 
    AS (SELECT *, 
       Row_number() OVER (PARTITION BY Topic, Position 
             ORDER BY Newid()) AS RN1 
     FROM QuestionBank), 
    T2 
    AS (SELECT *, 
       Row_number() OVER (ORDER BY RN1, Newid()) AS RN2 
     FROM T1), 
    T3 
    AS (SELECT *, 
       Row_number() OVER (PARTITION BY Hardness 
             ORDER BY RN2) AS RN3 
     FROM T2) 
SELECT Id, 
     Topic, 
     Hardness, 
     Position 
FROM T3 
WHERE (Hardness = 1 
     AND RN3 <= 3) 
     OR (Hardness = 2 
      AND RN3 <= 2) 
     OR (Hardness = 3 
      AND RN3 <= 2) 
ORDER BY Topic, 
      Position, 
      Hardness 

テーブルの一部を選択する場合は、たびに効率的な方法が選択されます。

+0

ありがとうございます@Martinはあなたのソリューションです。 私は昨日からそれに取り組み、完璧に動作します。 –

+0

私は別の問題を抱えていました: トピックの硬度の代わりにレコードの数を制限しようとすると、解決策は何でしょうか? トピック= 1の3レコード、トピック= 2の4レコード、トピック= 3の2レコード(硬度= 1の例2レコードの代わりに) おかげさまで、ありがとうございました。 –

0

質問を一度に選択するには、WHILEサイクルがあります。

  1. が同じで選択questinが以前にあった場合、それらの1つの
  2. テストを選択するために使用rand()
  3. 一時テーブルに硬度1のすべてのレコードを選択:ランダムな質問を選択するには

    トピック/位置が選択された質問に含まれていない場合は、ポイント1で選択したものから削除します。

  4. Nの硬度を指定するまで手順2〜3を実行します。
  5. 他の硬度値については、ステップ1〜4を実行します。
関連する問題