2

私が奇妙なことに出くわしたコードをレビューしたとき、誰かがあなたがABS(CHECKSUM(NewId())) % N0からN-1までの乱数を取得するために使用できることを読んでいました(RAND()行ごとには発生しません)が、彼らは実際にコードをテストしなかったと思います(テーブル変数を使用して簡略化され、実際のコードはTOP 1 country以下の問題を誤って回避しました):

DECLARE @Values TABLE
(
    id int identity,
    country VARCHAR(100)
)

INSERT INTO @Values (country) VALUES ('UK'), ('USA'), ('China')

SELECT *, (SELECT country FROM @Values v WHERE v.id = ABS(CHECKSUM(NewId())) % 3 + 1)
FROM @Values

実行すると、次のエラーが発生します。

サブクエリは複数の値を返しました。サブクエリが=、!=、<、<=、>、> =の後に続く場合、またはサブクエリが式として使用される場合、これは許可されません。

私の最初の質問は、サブクエリが複数の値をどのように返すことができるかということでした。そして、それが時々まったく価値を返さないのはどうしてですか?(私がSOで尋ねている質問ではないことに注意してください)テスト者:

SELECT country FROM @Values v WHERE v.id = ABS(CHECKSUM(NewId())) % 3 + 1

しかし、次のことが何度実行されても、次のようになります。

SELECT ABS(CHECKSUM(NewId())) % 3 + 1

返される結果は常に1,2,3です(これは、プログラマーがコードを作成するときに使用した「テスト」でした)

このすべてから、これはすべての行ではなくすべての比較に対して再実行されているためだと思います。誰かがこれを確認し、この動作を説明するための適切なリンクを提供して、彼に指摘できるようにすることができますか?

4

2 に答える 2

2

なぜ、これは予想されます。

ABS(CHECKSUM(NewId())) % 3 + 1は の行ごとに 1 回評価されるため、行ごと@Valuesに異なる値になります。

したがって、複数の行を返すことも、まったく行を返さないこともあります。

これはまさに、「この式はすべての行に対して評価されます」と言ったときに予想されることです。

どうやら実際に必要なのは、クエリごとに 1 回評価される式です。

于 2012-02-27T11:13:31.000 に答える
0

newID は常に行ごとに 1 回呼び出されます。一意の値が必要な場合は、次のように使用します。

ROUND(((3) * RAND() + 1), 0)

于 2012-02-27T12:41:29.440 に答える