3

小さなテーブルからランダムに10%のサンプリングを選択しようとしています。RAND()関数を使用して、乱数が0.10未満の行を選択すると思いました。

SELECT * FROM SomeTable
WHERE SomeColumn='SomeCondition' AND
      RAND() < 0.10

しかし、私はすぐにRAND()が常に同じ数を返すことを発見しました!このxkcdの漫画を思い出させます。

OK、問題ありません。RAND関数はシード値を取ります。このクエリは定期的に実行しますが、別の日に実行すると異なる結果が得られるようにしたいので、日付と一意の行IDの組み合わせをシードします。

SELECT * FROM SomeTable
WHERE SomeColumn='SomeCondition' AND
      RAND(CAST(GETDATE) AS INTEGER) + RowID) < 0.10

まだ結果が出ません!RANDから返された乱数を表示すると、それらがすべて狭い範囲内にあることがわかります。RANDから乱数を取得するには、ランダムシードを使用する必要があるようです。そもそも乱数シードがあれば、乱数は必要ありません!

私はこの問題に関連する以前の議論を見てきました:

SQL ServerランダムソートSQL
でランダム行を要求するにはどうすればよいですか?

彼らは私を助けません。TABLESAMPLEはページレベルで機能します。これは大きなテーブルには最適ですが、小さなテーブルには適していません。WHERE句の前に適用されるようです。必要な行数が事前にわからないため、NEWIDを使用したTOPは機能しません。

誰かが解決策、または少なくともヒントを持っていますか?

編集:私の特定のケースで機能するソリューションを提供してくれたAlexCuseに感謝します。さて、より大きな質問に、RANDをどのように動作させるか?

4

5 に答える 5

6

このタイプのアプローチ (ΤΖΩΤΖΙΟΥ で表示) は、10% のサンプリングを保証しません。Rand() が < .10 と評価され、一貫性がないすべての行のみが表示されます。

何かのようなもの

select top 10 percent * from MyTable order by NEWID()

トリックを行います。

編集: RAND を動作させる良い方法は実際にはありません。これは私が過去に使用したものです(クラッジアラート-UDFでRand()を使用できないと殺されます)

CREATE VIEW RandView AS 

SELECT RAND() AS Val

GO

CREATE FUNCTION RandomFloat()
RETURNS FLOAT
AS
BEGIN

RETURN (SELECT Val FROM RandView)

END

次にselect blah, dbo.RandomFloat() from table、クエリを実行するだけです。

于 2008-10-02T18:28:51.807 に答える
2

テーブルに、整数、浮動小数点、SQL数値など、一般的な意味で数値である列(おそらくROWID列)がある場合は、次のことを試してください。

SELECT * FROM SomeTable WHERE SomeColumn='SomeCondition' AND 0*rowid+RAND() < 0.10

クエリの開始時に1回ではなく、すべての行RAND()に対して1回評価するため。

クエリオプティマイザが原因です。別の方法があるかもしれませんが、これでうまくいくと思います。

于 2008-10-02T17:43:18.080 に答える
1

これはうまくいくようです:

select * from SomeTable
where rand(0*SomeTableID + cast(cast(newid() as binary(4)) as int)) <= 0.10
于 2008-10-02T19:45:21.797 に答える
0

これはうまくいくようです

SELECT TOP 10 PERCENT * FROM schema.MyTable ORDER BY NEWID()
于 2011-01-26T15:00:55.300 に答える
0

この質問を見ましたか?

SQL Server 2005 で乱数を列として返すにはどうすればよいですか?

Adam は、Rand() の代わりに使用できる UDF を投稿しました。

于 2008-10-02T19:43:30.677 に答える