私の実際の作業クエリは内部結合でしたが、クロス結合を使用したこの単純な例では、ほとんど常に問題が再現されているようです。
SELECT *
FROM (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
CROSS JOIN (
SELECT NEWID() TEST_ID
) BB ( B )
私の内部結合では、NEWID()関数を使用して各行にGUIDを追加した多くの行があり、そのような行の約9に対して、2行の仮想テーブルとの乗算により期待される結果が生成されました。同じGUID。10のうち1つは異なる結果を生成します。これは控えめに言っても予想外であり、テストデータ生成スクリプトでこのバグを見つけるのに本当に苦労しました。
非決定的なgetdate関数とsysdatetime関数を使用して次のクエリを見ると、これは表示されません。私はとにかく、両方の最終結果行に常に同じdatetime値を表示しています。
SELECT *
FROM (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
CROSS JOIN (
SELECT GETDATE() TEST_ID
) BB ( B )
SELECT *
FROM (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
CROSS JOIN (
SELECT SYSDATETIME() TEST_ID
) BB ( B )
私は現在SQL Server 2008を使用していますが、今の私の回避策は、ランダムデータ生成スクリプトを完了する前に、GUIDを含む行をテーブル変数に読み込むことです。仮想テーブルではなくテーブルの値としてそれらを取得すると、問題はなくなります。
回避策はありますが、実際のテーブルやテーブル変数なしで回避策を探しています。
これを書いている間、私は成功せずにこれらの可能性を試しました:1)ネストされた仮想テーブルにnewid()を配置します:
SELECT *
FROM (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
CROSS JOIN (
SELECT TEST_ID
FROM (
SELECT NEWID() TEST_ID
) TT
) BB ( B )
2)次のようなキャスト式内でnewid()をラップします。
SELECT CAST(NEWID() AS VARCHAR(100)) TEST_ID
3)結合式内の仮想テーブルの出現順序を逆にする
SELECT *
FROM (
SELECT NEWID() TEST_ID
) BB ( B )
CROSS JOIN (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
4)相関のない相互適用の使用
SELECT *
FROM (
SELECT NEWID() TEST_ID
) BB ( B )
CROSS APPLY (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
ついにこの質問を投稿する直前に、今私はこれを試して成功したようです、相関のあるクロスが適用されます:
SELECT *
FROM (
SELECT NEWID() TEST_ID
) BB ( B )
CROSS APPLY (
SELECT A
FROM (
SELECT 1 UNION ALL
SELECT 2
) TT ( A )
WHERE BB.B IS NOT NULL
) AA ( A )
誰か他のよりエレガントでシンプルな回避策がありますか?必要がない場合は、単純な行の乗算に相互適用または相関を使用したくありません。