SQLサーバーのテーブルからランダムなレコードを取得する簡単な方法はありますか?
ユニットテストデータをランダム化したいので、テーブルからランダムIDを選択する簡単な方法を探しています。英語での選択は、「テーブルからIDを1つ選択します。IDは、テーブル内の最小IDとテーブル内の最大IDの間の乱数です」。
クエリを実行し、null値をテストし、nullの場合は再実行する必要なしに、それを行う方法がわかりません。
アイデア?
SQLサーバーのテーブルからランダムなレコードを取得する簡単な方法はありますか?
はい
_SELECT TOP 1 * FROM table ORDER BY NEWID()
_
NEWID()
が各行に対して生成され、テーブルはそれによってソートされます。最初のレコードが返されます(つまり、「最も低い」GUIDを持つレコード)。
GUIDは、バージョン4以降の擬似乱数として生成されます。
バージョン4 UUIDは、真の乱数または擬似乱数からUUIDを生成するためのものです。
アルゴリズムは次のとおりです。
- Clock_seq_hi_and_reservedの2つの最上位ビット(ビット6および7)をそれぞれ0および1に設定します。
- Time_hi_and_versionフィールドの最上位4ビット(ビット12〜15)をセクション4.1.3の4ビットバージョン番号に設定します。
- 他のすべてのビットをランダムに(または擬似ランダムに)選択した値に設定します。
代替のSELECT TOP 1 * FROM table ORDER BY Rand()
は、考えられるようには機能しません。 Rand()
はクエリごとに1つの値を返すため、すべての行が同じ値を共有します。
GUID=値は擬似ランダムですが、より要求の厳しいアプリケーションには、より良いPRNGが必要です。
通常、システムによって異なりますが、通常は約1,000,000行で10秒未満のパフォーマンスです。インデックスにヒットすることは不可能であるため、パフォーマンスは比較的制限されることに注意してください。
大きなテーブルでは、TABLESAMPLE
を使用してテーブル全体をスキャンしないようにすることもできます。
SELECT TOP 1 *
FROM YourTable
TABLESAMPLE (1000 ROWS)
ORDER BY NEWID()
ORDER BY NEWID
は、データページで最初に表示される行を返すことを避けるために必要です。
使用する数値は、テーブルのサイズと定義のために慎重に選択する必要があり、行が返されない場合は再試行ロジックを検討できます。この背後にある数学と、この手法が小さなテーブルに適さない理由は、 ここで説明
また、メソッドを試してMIN(Id)とMAX(Id)の間のランダムIDを取得してから、
SELECT TOP 1 * FROM table WHERE Id >= @yourrandomid
常に1行になります。
大きなデータを選択する場合、私が知っている最良の方法は次のとおりです。
SELECT * FROM Table1
WHERE (ABS(CAST(
(BINARY_CHECKSUM
(keycol1, NEWID())) as int))
% 100) < 10
ソース: [〜#〜] msdn [〜#〜]
私が試した方法を改善したいと考えていたので、この投稿に出くわしました。古いことはわかっていますが、この方法はリストされていません。テストデータを作成および適用しています。これは、SP @st(2文字の状態)で呼び出された場合の「アドレス」のメソッドを示しています
Create Table ##TmpAddress (id Int Identity(1,1), street VarChar(50), city VarChar(50), st VarChar(2), Zip VarChar(5))
Insert Into ##TmpAddress(street, city, st, Zip)
Select street, city, st, Zip
From tbl_Address (NOLOCK)
Where st = @st
-- unseeded Rand() will return the same number when called in rapid succession so
-- here, I seed it with a guaranteed different number each time. @@ROWCOUNT is the count from the most recent table operation.
Set @csr = Ceiling(Rand(convert(varbinary, newid())) * @@ROWCOUNT)
Select street, city, st, Right(('00000' + ltrim(Zip)),5) As Zip
From ##tmpAddress (NOLOCK)
Where id = @csr