これは間違いなく製品のバグです。
同様のバグ が既に報告され、次のようにクローズされました。 「直らない」 .
この質問、リンクされた接続項目、および 別の
2
このサイトに関する質問 インライン TVF と OUTER APPLY
を使用して、このタイプの動作の 4 つのケースを見てきました。 - それらはすべて
OUTER APPLY dbo.SomeFunction(...) F
と書くと正しい結果が返ってきました
OUTER APPLY (SELECT * FROM dbo.SomeFunction(...)) F
したがって、これは可能な回避策のようです。
クエリについて
WITH Test AS
(
SELECT 12 AS PropertyID,
$350000 AS Ap1,
350000 AS Ap2
)
SELECT LP.*
FROM Test T
OUTER APPLY dbo.TVFTest
(
T.PropertyID,
T.Ap1,
T.Ap2
) LP;
実行計画は次のようになります
そして、最終的な射影の出力列のリストは次のとおりです。 Expr1000、Expr1001、Expr1003、Expr1004.
ただし、これらの列のうち、右下の定数のテーブルで定義されているのは 2 つだけです。
リテラル $350000
右上の定数の表に定義されています (Expr1001)。これは、右下の定数テーブルに外部結合されます。結合条件に一致する行がないため、そこで定義されている 2 つの列 (Expr1003、Expr1004) は正しく NULL として評価されます。最後に、計算スカラーはリテラル 12
を追加します 外部結合の結果に関係なく、新しい列 (Expr1000) としてデータ フローに挿入されます。
これらはまったく正しいセマンティクスではありません。インライン TVF を手動でインライン化した場合の (正しい) プランと比較してください。
WITH Test
AS (SELECT 12 AS PropertyID,
$350000 AS Ap1,
350000 AS Ap2)
SELECT LP.*
FROM Test T
OUTER APPLY (SELECT KeyID,
MatchValue1,
MatchValue2,
CASE
WHEN MatchValue1 <> MatchValue2
THEN 'Not equal'
ELSE 'Something else'
END AS MatchTest
FROM (SELECT T.PropertyID AS KeyID,
T.Ap1 AS MatchValue1,
T.Ap2 AS MatchValue2) TestRow
WHERE MatchValue1 <> MatchValue2) LP
ここで、最終的な射影で使用される列は Expr1003, Expr1004, Expr1005, Expr1006
です。 .これらはすべて、右下の定数スキャンで定義されています。
TVF の場合、非常に早い段階ですべてがうまくいかないようです。
OPTION (RECOMPILE, QUERYTRACEON 3604, QUERYTRACEON 8606);
の追加 プロセスへの入力ツリーが既に正しくないことを示しています。 SQL で表現すると、次のようになります。
SELECT Expr1000,
Expr1001,
Expr1003,
Expr1004
FROM (VALUES (12,
$350000,
350000)) V1(Expr1000, Expr1001, Expr1002)
OUTER APPLY (SELECT Expr1003,
IIF(Expr1001 <> Expr1003,
'Not equal',
'Something else') AS Expr1004
FROM (SELECT CAST(Expr1002 AS MONEY) AS Expr1003) D
WHERE Expr1001 <> Expr1003) OA
そのトレース フラグの完全な出力は次のとおりです (8605 は基本的に同じツリーを示しています)。
*** Input Tree: ***
LogOp_Project COL: Expr1000 COL: Expr1001 COL: Expr1003 COL: Expr1004
LogOp_Apply (x_jtLeftOuter)
LogOp_Project
LogOp_ConstTableGet (1) [empty]
AncOp_PrjList
AncOp_PrjEl COL: Expr1000
ScaOp_Const TI(int,ML=4) XVAR(int,Not Owned,Value=12)
AncOp_PrjEl COL: Expr1001
ScaOp_Const TI(money,ML=8) XVAR(money,Not Owned,Value=(10000units)=(-794967296))
AncOp_PrjEl COL: Expr1002
ScaOp_Const TI(int,ML=4) XVAR(int,Not Owned,Value=350000)
LogOp_Project
LogOp_Select
LogOp_Project
LogOp_ConstTableGet (1) [empty]
AncOp_PrjList
AncOp_PrjEl COL: Expr1003
ScaOp_Convert money,Null,ML=8
ScaOp_Identifier COL: Expr1002
ScaOp_Comp x_cmpNe
ScaOp_Identifier COL: Expr1001
ScaOp_Identifier COL: Expr1003
AncOp_PrjList
AncOp_PrjEl COL: Expr1004
ScaOp_IIF varchar collate 53256,Var,Trim,ML=14
ScaOp_Comp x_cmpNe
ScaOp_Identifier COL: Expr1001
ScaOp_Identifier COL: Expr1003
ScaOp_Const TI(varchar collate 53256,Var,Trim,ML=9) XVAR(varchar,Owned,Value=Len,Data = (9,Not equal))
ScaOp_Const TI(varchar collate 53256,Var,Trim,ML=14) XVAR(varchar,Owned,Value=Len,Data = (14,Something else))
AncOp_PrjList
*******************