Часть вашего первоначального запроса выглядит следующим образом.
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значений.