Частина вашого початкового запиту полягає в наступному.
FROM [dbo].[calendar] a
LEFT JOIN [dbo].[colleagueList] b
ON b.[Date] = a.d
WHERE DAY(a.[d]) = 1
AND a.[d] BETWEEN @dateStart AND COALESCE(@dateEnd,@dateStart)
Цей розділ плану показано нижче

Ваш переглянутий запит BETWEEN @dateStart AND ISNULL(@dateEnd,@dateStart)має це для того ж приєднання

Відмінність полягає в тому, що ISNULLдалі спрощується, і в результаті ви отримуєте більш точну статистику про кардинальність, переходячи до наступного з'єднання. Це функція вбудованої таблиці, яку ви оцінюєте, і ви називаєте її буквальними значеннями, щоб вона могла робити щось подібне.
a.[d] BETWEEN @dateStart AND ISNULL(@dateEnd,@dateStart)
a.[d] BETWEEN '2013-06-01' AND ISNULL(NULL,'2013-06-01')
a.[d] BETWEEN '2013-06-01' AND '2013-06-01'
a.[d] = '2013-06-01'
А коли є предикат приєднання еквівалента, b.[Date] = a.dплан також показує предикат рівності b.[Date] = '2013-06-01'. В результаті оцінка кардинальності 28,393рядків, ймовірно, буде досить точною.
Для CASE/ COALESCEверсії, коли @dateStartі @dateEndє однакове значення, тоді воно спрощує ОК до того ж виразу рівності і дає той самий план, але коли @dateStart = '2013-06-01'і @dateEnd IS NULLце іде лише до
a.[d]>='2013-06-01' AND a.[Date]<=CASE WHEN (1) THEN '2013-06-01' ELSE NULL END
який він також застосовується як неявний присудок на ColleagueList. Орієнтовна кількість рядків цього разу - це 79.8рядки.
Наступним приєднанням є
LEFT JOIN colleagueTime
ON colleagueTime.TC_DATE = colleagueList.Date
AND colleagueTime.ASSOC_ID = CAST(colleagueList.ID AS VARCHAR(10))
colleagueTime- це 3,249,590таблиця рядків, яка (знов), мабуть, купа без корисних індексів.
Ця невідповідність оцінок впливає на використаний вибір приєднання. ISNULLПлан вибирає хеширования , який просто переглядає таблицю один раз. COALESCEПлан вибирає вкладені цикли і оцінок , що він все одно буде просто необхідний сканувати таблицю один раз і мати можливість намотати результат і повторити його 78 разів. тобто він оцінює, що корельовані параметри не зміняться.
Зважаючи на те, що план вкладених циклів все ще тривав через дві години, таке припущення про одне сканування проти, colleagueTimeздається, є дуже неточним.
Щодо того, чому орієнтовна кількість рядків між двома з’єднаннями настільки нижча, я не впевнений, не маючи змоги побачити статистику на таблицях. Єдиний спосіб, коли мені вдалося перекрутити підрахунок підрахунків рядків, що значною мірою в моєму тестуванні було додавання навантаження NULLрядків (це зменшило приблизну кількість рядків, хоча фактична кількість повернених рядків залишилася колишньою).
Орієнтовна кількість рядків у COALESCEплані з моїми тестовими даними була в порядку
number of rows matching >= condition * 30% * (proportion of rows in the table not null)
Або в SQL
SELECT 1E0 * COUNT([Date]) / COUNT(*) * ( COUNT(CASE
WHEN [Date] >= '2013-06-01' THEN 1
END) * 0.30 )
FROM [dbo].[colleagueList]
але це не суперечить вашому коментарю, що стовпець не має NULLзначень.