1

タイプされた質問の表があります: Select One, True False,Select All タイプの 1 つを返されるタイプの特定のパーセンテージに制限しながら、特定の数の質問を返すクエリを作成しようとしています。

例:

SELECT QuestionID, QuestionText, QuestionType
FROM Question
WHERE/HAVING --limit QuestionTypeID = 4 to be only 10% of total returned

私の最初の考えは、クエリを個別にプルすることでした

SELECT TOP 10 PERCENT QuestionID, QuestionText, QuestionType
FROM Question
WHERE QuestionTypeID <> 4
UNION ALL
SELECT QuestionID, QuestionText, QuestionType
FROM Question
WHERE QuestionTypeID = 4

ただし、これを計算するより効率的な方法がおそらくあるようです。


編集:

私が達成しようとしていることを明確にさせてください...他のタイプの質問の混合物を90%返し、タイプ4の10%のみを返す必要があります。

結果をランダム化する必要があるため、使用SET ROWCOUNTしてきましたORDER BY NEWID()

サブクエリを使用できますがSET ROWCOUNT、サブクエリで使用する方法がわかりません...この時点では、一時テーブルが必要なようですが、より良い方法があれば教えてください...

私がこれまでに持っているもの...一時テーブル

DECLARE @ReturnPercent [int] --variable that holds percentage for bottom questions
DECLARE @ReturnCount [int] --variable that holds how many questions I'd like returned

CREATE TABLE #Temp1(
        QuestionID [int], 
        QuestionText [nvarchar](256), 
        QuestionTypeID [int]
);

DECLARE @TOP [int] = @ReturnCount-CAST(@ReturnCount*@ReturnPercent AS INT);
DECLARE @BOTTOM [int] = CAST(@ReturnCount(@ReturnPercent AS INT);

SET ROWCOUNT @TOP
INSERT INTO #Temp1(QuestionID, QuestionText, QuestionTypeID)
SELECT QuestionID, QuestionText, QuestionTypeID
FROM Question
WHERE QuestionTypeID <> 4
ORDER BY NEWID()
SET ROWCOUNT 0

SET ROWCOUNT @BOTTOM
INSERT INTO #Temp1(QuestionID, QuestionText, QuestionTypeID)
SELECT QuestionID, QuestionText, QuestionTypeID
FROM Question
WHERE QuestionTypeID = 4
ORDER BY NEWID()
SET ROWCOUNT 0

--Query to join them with other data(omitted) 
SET ROWCOUNT @ReturnCount
SELECT a.QuestionID, a.QuestionText, a.QuestionTypeID
FROM #Temp1 a
JOIN --OTHER TABLES FOR FULL QUERY
ORDER BY NEWID()
SET ROWCOUNT 0
4

1 に答える 1

0

ユニオンオールは、おそらくこれを行うための最も効率的な方法です。

すべての行に行番号を割り当てる効率的な方法があります。

SELECT row_number() over (order by (select NULL)) as seqnum

ただし、パーティション句を追加した場合、これは効率的ではないと思います。これが効率的で、質問IDにインデックスがある場合は、次を使用できます。

select q.QuestionID, q.QuestionText, q.QuestionType
from (select QuestionID, QuestionText, QuestionType,
             row_number() over (partition by QuestionId order by (select NULL)) as seqnum
      from Question
     ) q join
     (select QuestionId, count(*) as cnt
      From Question
      group by Questionid
     ) qsum
     q.questionid = qsum.questionid
where questionid <> 4 or seqnum*1.0/cnt <= 0.1

(group byはインデックスによって満たされ、結合は非常に安価で、row_number()は効率的であるという考え方です。)

しかし、私は、組合はすべておそらくより速いと思います。

うーん、今考えてみると、近似でかなり遠くまで行くことができます:

select q.QuestionID, q.QuestionText, q.QuestionType
from (select QuestionID, QuestionText, QuestionType,
             row_number() over (order by (select NULL)) as seqnum
      from Question
     ) q
where mod(seqnum, 10) <> 0 and questionid <> 4 or
      mod(seqnum, 10) = 0 and questionid = 4

これは、questionid <> 4の場合は行の約90%、questionid = 4の場合は約10%を占めます。このフレーズのrow_number()は、並べ替えや分割なしで連続番号を割り当てるため、これは非常に効率的です。

于 2012-06-02T01:51:34.460 に答える