これは SQL Server 2008 です。次の 2 つのテーブルと結合があります。
DECLARE @EmployeeCrossDay TABLE
(
EmployeeId UNIQUEIDENTIFIER,
WorkDate DATE, OtherStuff...
)
DECLARE @ET TABLE
(
EmployeeId UNIQUEIDENTIFIER,
WorkDate DATE, DifferentOtherStuff...
)
SELECT *
FROM @EmployeeCrossDay ecd
LEFT JOIN @ET et ON et.EmployeeId = ecd.EmployeeId
AND et.WorkDate = ecd.WorkDate
最初のテーブルには 5,680 行 (範囲内の各日付の従業員ごとに 1 行)、2 番目のテーブルには 397 行 (従業員が実際に働いた日ごとに 1 行以上) があります。(したがって、EmployeeId/WorkDate は、最初のテーブルでは一意の組み合わせですが、2 番目のテーブルではそうではありません。) クエリの結果は正しいです (各従業員のリストには、勤務した日の 1 つ以上の行と、各日の行があります)。彼はうまくいきませんでした)、しかしそれには約 3 秒かかり、私のプロファイルは途中でデカルト積を示しています (2,254,960 行)。完全なクロス結合を防ぐためにこのクエリを再構築する方法はありますか?
*編集済み* 主キーを追加した後、提案されているように、Showplan_Textをオンに設定すると、次のようになります。
|--Compute Scalar(DEFINE:([Expr1007]=isnull(@ET.[StartTime] as [et].[StartTime],[Expr1010]), [Expr1008]=isnull(@ET.[EndTime] as [et].[EndTime],[Expr1010])))
|--Nested Loops(Left Outer Join, OUTER REFERENCES:([et].[ServiceCallId]))
|--Compute Scalar(DEFINE:([Expr1006]=isnull(@ET.[TypeId] as [et].[TypeId],(8)), [Expr1009]=isnull(@ET.[Interrupt] as [et].[Interrupt],($0.0000))))
| |--Nested Loops(Left Outer Join, WHERE:(@ET.[EmployeeId] as [et].[EmployeeId]=@EmployeeCrossDay.[EmployeeId] as [ecd].[EmployeeId] AND @ET.[WorkDate] as [et].[WorkDate]=@EmployeeCrossDay.[WorkDate] as [ecd].[WorkDate]))
| |--Compute Scalar(DEFINE:([Expr1010]=CONVERT_IMPLICIT(datetime,@EmployeeCrossDay.[WorkDate] as [ecd].[WorkDate],0)))
| | |--Sort(ORDER BY:([ecd].[Number] ASC, [ecd].[WorkDate] ASC))
| | |--Clustered Index Scan(OBJECT:(@EmployeeCrossDay AS [ecd]))
| |--Clustered Index Scan(OBJECT:(@ET AS [et]))
|--Clustered Index Seek(OBJECT:([Snapper].[dbo].[ServiceCalls].[PK_Jobs] AS [sc]), SEEK:([sc].[ServiceCallId]=@ET.[ServiceCallId] as [et].[ServiceCallId]) ORDERED FORWARD)
「途中でデカルト積を表示する」とは、Statistics Profile をオンに設定することに由来します。ここに貼り付けるには多すぎますが、プランの最後から 2 番目の項目 (クラスター化インデックス スキャン) では、行の下に 2,254,960 (私のコンマ)、実行の下に 5680 が表示されます。私はデカルト積を持っていると誤解していますか?