2016-09-05 5 views
9

選択:奇妙な行動 - ランダム私は時間のために、以下のステートメントをデバッグされている

SELECT 
(
SELECT t1.anotherColumn 
FROM table1 t1 
WHERE t1.aColumn=(1+ABS(Checksum(NewId()))%54) 
) res, * 
FROM 
(
SELECT TOP 200 * --PLEASE NOTICE HERE 
FROM table2 
)RESULT 

と問題が常にresは、各行に対して同じ値が含まれていることです。ここで、176より下の任意の数字にクエリ文でハイライトされている200を変更すると、希望の結果であるtable1のランダムな行が表示されます。
54は結果に影響を及ぼさないことに注意してください。私のテーブルはaColumnに対して1から54までの54の異なる値を持つためです。
私はこのテーブルを別のテーブルで試してみましたが、この奇妙な動作が繰り返されています!

+0

クエリオプティマイザがここで動作しているようです。 –

+0

@TimBiegeleisen SQL Serverがシーンの裏側で何かをしていることがわかりました。それはおそらくクエリオプティマイザです。どうか知っていなければわかりません。ところで、ありがとう、私のためにそれをしないでくださいと言う方法があるはずです! – mok

+0

各結果行に対して最初のサブクエリを実行するようにエンジンを強制する必要があります。最初のサブクエリにダミー条件を追加して、「AND result.id is not null」のような相関クエリを作成してください。 – trincot

答えて

4

結果の違いは、クエリプランの違いによって説明できます。

SQLオプティマイザは、テーブルスプール/レイジースプール演算子を使用することを選択できます。この場合、NEWID()は一度呼び出され、GUIDは一時表に格納され、他のすべての行に使用されます。

https://technet.microsoft.com/en-us/library/ms191221(v=sql.105).aspx

... UPDATE: クエリプランは一番下に線の下に追加して固定することができます、

option(use plan 
N' 
<your XML plan> 
') 

が "良い" XMLプランをキャッチするために実行

SET SHOWPLAN_XML ON 

とし、期待される結果を示すクエリを実行します。コピー&ペーストこのソリューションは、行(百万人)の数が多いために私の作品OPTION(利用計画...)

にそれを

+0

私はあなたがテーブルの1千の行を持っているとき、あなたが余りにも多くのレコード(千)をプールしているとき、常に働かないので、ソリューション(GETDATE()> '2011-01-01')を一時的に削除しなければなりませんでした。私はそれがまだ必要であれば明日もう一つ用意します。実際には行数に依存しますので、テーブルが小さければそれを使用できます。 – Anton

+0

ありがとうございました少なくとも私は問題の根本を知っています。私はそれが明日もうまくいくようにするつもりです。時にはテーブルが大きすぎることもあります。 – mok

+0

クエリプランを修正するには、「良い」プランを保存してから、「USE PLAN」クエリヒントを再利用します。 https://technet.microsoft.com/en-us/library/ms186954(v=sql.105).aspx – Anton

2

これは、すべての行にreevaulatedされるサブクエリを強制し、複雑を回避しますランダムロジック。 NEWID()が既にランダム一意の識別子とTABLE1の各行は表2の行と照合されるtable2の力に比較したものであるため

SELECT top 200 
    (SELECT top 1 t1.anotherColumn from table1 t1 with(nolock) where t2.t2Id is not null order by newid() ) res, 
    * 
FROM table2 t2 

は、それが動作します。