- Не пишите запросы, которые используют функции для столбцов для сравнения с константами.Это делает их недоступными для SARG, и невозможно использовать конечный индекс для столбца
setDate
. - Не используйте литералы, где можно использовать параметр
- Если необходимо использовать литералыдля даты и времени используйте формат неразделенной строки , поскольку он не зависит от языка и всегда интерпретируется как
ymd
.
В заключение:
SELECT COUNT(td.timeSheetID) FROM TimeSheet t
INNER JOIN TimeSheetDetail td ON t.timeSheetID = td.timeSheetID
WHERE t.setDate BETWEEN @dateFrom AND @dateTo
AND t.employeeID = @employeeId;
или (хуже):
SELECT COUNT(td.timeSheetID) FROM TimeSheet t
INNER JOIN TimeSheetDetail td ON t.timeSheetID = td.timeSheetID
WHERE t.setDate BETWEEN '20120810' AND '20120812'
AND t.employeeID = 300;
Что касается вашего вопроса, лучший способ отсканировать «день» в диапазоне даты и времени - это выразить день как диапазон:
SELECT COUNT(td.timeSheetID) FROM TimeSheet t
INNER JOIN TimeSheetDetail td ON t.timeSheetID = td.timeSheetID
WHERE t.setDate >= '20120811' AND t.setDate < '20120812'
AND t.employeeID = 300;
Это будет охватывать все часы 20120811. Разумеется, лучше ли использовать параметры вместо литералов.
И, наконец, реальный вопрос будет, если у вас есть индекс покрытия для этого запроса.Временные ряды, как и таблица «расписания», почти всегда связаны по диапазону дат, поэтому кластерный индекс по (employeeID, setDate)
, вероятно, является хорошим выбором.Второй лучший выбор - некластеризованный индекс для того же самого.