2009-09-16 17 views
0

私の同僚は、私が知らなかったSQL Serverの動作を発見しました。このこれは、各レコードの乱数を生成する良い方法か悪い方法ですか?

CREATE VIEW dbo.vRandNumber AS 
SELECT RAND() as RandNumber 
GO 

CREATE FUNCTION dbo.RandNumber() RETURNS float AS 
RETURN (SELECT RandNumber FROM vRandNumber) 
GO 

DECLARE @mytable TABLE (id INT) 
INSERT INTO @mytable SELECT 1 
INSERT INTO @mytable SELECT 2 
INSERT INTO @mytable SELECT 3 

SELECT *, dbo.RandNumber() FROM @mytable 

は、データセット内の各レコードの「ランダム」値を生成する最も簡単な方法であることをです。しかし、それが文書化された行動の結果であるのか、偶然の奇妙な収束を利用したのかは完全にはわかりません。

のようなものを使用しますか?


EDIT

これは、RAND()関数自体のメリットについての質問ではなく、UDF/VIEWの組合せの使用は、すべての行に再計算することを強制します。 (dbo.RandNumber()の代わりに最終的なクエリでRAND()を使用すると、すべてのレコードに同じ値が与えられます)。

また、ポイントは値を表示するたびに異なります。たとえばレコードのランダムな選択を可能にします。 SQL Serverの2000+のために

EDIT

答えて

3

今後のバージョンのSQL Serverで作業を続けたいと思っているソフトウェアでは、これを実行しません。 select文の各行に対してRAND()から異なる値を返す方法が見つかりました。この発見は、1)少しのハック、2)SQL Server 2005で作成されました。これはSQL Server 2008で動作しなくなりました。この経験により、rand()にランダムな値行。

また、SQL ServerはUDFへの複数の呼び出しを最適化することができますが、現在はいくつかの非決定的な機能が可能になっているので、変更されている可能性があります。

SQL Server 2005の場合のみ、select文で行ごとにrand()を強制的に実行する方法。また、私はあなたが)(RANDのランダム性について尋ねていなかったが、私は良い参考と述べ知っ

create table #t (i int) 
insert into #t values (1) 
insert into #t values (2) 
insert into #t values (3) 

select i, case when i = 1 then rand() else rand() end as r 
from #t 

1 0.84923391682467 
2 0.0482397143838935 
3 0.939738172108974 

は2008年 2005年以前にいずれかのバージョンでテストされていないSQL Server上では動作しませんは:http://msdn.microsoft.com/en-us/library/aa175776(SQL.80).aspxです。これは、rand()をnewid()とrand(FunctionOf(PK、現在の日時))と比較します。

+0

CHECKSUM(NEWID())はSQL 2000以上で動作します。これは、SQL 2005パッチで削除される可能性のある特定の動作に依存します。 – gbn

0

私はSQLの行ごとにランダムな番号を選択しなければならなかった、とあなたは... RAND()が真の乱数を生成していることを私に証明することができれば

はい。私はおそらくそのようなものを使うだろう。

1

ランダム値が必要な項目によって異なります。また、私はランダムに行をソートする必要がある場合、私は

同様
SELECT * 
FROM [MyTable] 
ORDER BY newID() 

ような何かを、あなたがintsのテーブルを生成することができますなど、

を、あなたはINTEGERに値を必要とする形式に依存しVARCHAR SQL ServerのID「機能」を使用して同様のクエリを実行すると、乱数が返されます。

私の同僚は、行ごとにランダムな整数が必要なので、テーブルに計算フィールドを追加し、クエリで返される行ごとに1つの乱数(整数)を生成します。私はこれをお勧めしているのか分からない。それは特定のツールで問題を引き起こしましたが、テーブルごとにランダムな整数を与えました。 newid()とそのテーブルを組み合わせて、必要に応じて乱数セットを得ることができます。

だから私はに戻ってきます。あなたはそれが必要なものを詳しく説明できますか?

更新:ここでは、テーブル定義がある私の同僚は、計算列を持っていたスニペット、行ごとに異なる乱数、テーブルが照会されるたびに返さ:私はこれを使用することはありません

CREATE TABLE [dbo].[Table](
    -- ... 
    [OrderID] [smallint] NOT NULL, --Not sure what happens if this is null 
    -- ... 
    [RandomizeID] AS (convert(int,(1000 * rand(([OrderID] * 100 * datepart(millisecond,getdate())))))), 
    -- ... 
) 
+0

を(むしろRAND() * xxxより)乱数を生成するためにCHECKSUM(NEWID())を使用するか、または新しいSQL Serverの思い。そのためには毎回異なる記録が必要です。おそらく重み付けされていますが、[weight] * dbo.RandNumber()を使用しています。つまり、各レコードのランダムに生成された行を取得する方法です。これは、テーブルをクエリするたびに異なります。 – MatBailie

+0

私はsql-2000と互換性がありませんでしたが、(afaik)newID()は乱数を返しません。それは、時間、ハードウェアなどに基づいているので、実際にランダムではない数字(例えば、ウェイトを乗算するために使用される)ではありません。しかし、RAND()よりランダムではないかどうかはわかりません関数。 – MatBailie

+0

あなたの同僚が計算フィールドに入れる計算は何ですか?私はちょうどRAND()を使って試してみましたが、実行ごとに異なる値が得られましたが、すべてのレコードに同じ値が設定されています... – MatBailie

0

を。私が知る限り、RAND()はシードとしてシステム時間を使用し、互いに急速に2回以上実行されると同じ値を生成します。たとえば、これを試してみてください:

SELECT *, 
      RAND() 
FROM  SomeTable 

RAND()は、各行に同じ値を与えます。

+1

この動作は時間の近さによるものではありません。これは、RAND()が1回だけ実行され、レコードごとに1回実行されないためです。また、この例ではRAND()を使用していますが、UDFとVIEWの後ろで難読化しています。このように毎回再計算を強制する。私の例では、すべての3つのレコードが毎回異なる値を取得します。彼らはどれほどランダムで、わからない。しかし、彼らは確かに(偶然を除いて)同じになることはありません。 – MatBailie

+0

私のクエリはRAND()のメリットに関するものではなく、UDF/VIEWコンボを使用してすべての行に対して再密接化を強制するメリットがあります。 – MatBailie

+1

ああ、そうだ。レコードセットごとに1回だけ実行するRAND()に関する情報をありがとう、私はこれを知らなかった。また、あなたの質問を誤解して申し訳ありません。 –

0

私はビューとudfのアプローチが不器用です。欠陥のある関数を使用するために余分なオブジェクトが必要です。

私はそれは、ランダムにレコードセットから行を取得するだけの場合はかなり学術的だ現在では2008 CRYPT_GEN_RANDOM

+0

NEWID()はRAND()と同じ方法でconstanstを解決しませんか?ビュー/ udfの組み合わせはまだ必要ですか? (これは本質的に疑問のあるview/udfの組み合わせであり、通常は各レコードに対して再評価される定数式とみなされます) – MatBailie

+0

NEWID()は、ステートメントごとではなく、呼び出しごとに*です。したがって、行ごとに異なるでしょう。 – gbn

+0

私の一般的な答え:http://stackoverflow.com/search?q = newid + RAND + user%3A27535 – gbn