WITH limits AS
(
SELECT COALESCE(@startDate, MIN(mydate)) AS startDate, COALESCE(@endDate, MAX(mydate)) AS endDate
FROM mytable
)
SELECT m.*
FROM limits
JOIN mytable m
ON mydate BETWEEN startDate AND endDate
Это будет наиболее эффективным, если есть индекс на mydate
, так как это условие можно настроить и будет использовать поиск индекса
.
Если индекса нет, используйте конструкции IFNULL
, предложенные другими.
SELECT
Column1,....
FROM MyTable
WHERE MyTable.StartDate>=COALESCE(@startDate,CONVERT(datetime,'01/01/1753'))
AND MyTable.EndDate<=COALESCE(@endDate,CONVERT(datetime,'12/31/9999'))
также, вот очень исчерпывающая статья по этой теме:
Условия динамического поиска в T-SQL, Эрланд Соммарског
он охватывает все проблемы и методы попыток написания запросов с несколькими дополнительными условиями поиска
вот оглавление:
Introduction
The Case Study: Searching Orders
The Northgale Database
Dynamic SQL
Introduction
Using sp_executesql
Using the CLR
Using EXEC()
When Caching Is Not Really What You Want
Static SQL
Introduction
x = @x OR @x IS NULL
Using IF statements
Umachandar's Bag of Tricks
Using Temp Tables
x = @x AND @x IS NOT NULL
Handling Complex Conditions
Hybrid Solutions – Using both Static and Dynamic SQL
Using Views
Using Inline Table Functions
Conclusion
Feedback and Acknowledgements
Revision History
Вы можете сделать это:
SELECT blah
FROM MyTable
WHERE
(@startDate IS NULL OR MyTable.StartDate >= @startDate)
AND (@endDate IS NULL OR MyTable.EndDate <= @endDate)
Но имейте в виду, что большое количество параметров в таких предложениях AND может привести к некорректному кэшированию планов запросов. В SO возникает много вопросов о неправильных планах запросов и об обнаружении параметров.
SELECT *
FROM MyTable
WHERE
MyTable.StartDate >= COALESCE(MyTable.StartDate, "1/1/1900")
/* Date selected as earliest plausible constant to avoid min() lookup */
AND MyTable.EndDate <= COALESCE(MyTable.EndDate, "1/1/3001")
/* Date selected as latest plausible constant to avoid max() lookup */
Очевидно, вам необходимо выбрать правильные константы для вашего приложения / домена. Это немного рискованно, если у вас недостаточно широкие константы, но намного быстрее, чем явно искать min / max из таблицы, а большинство приложений / доменов имеют довольно хорошо определенные фреймы.
Ответ Квассной, вероятно, лучший, но вот еще один вариант:
SELECT *
FROM MyTable
WHERE
MyTable.StartDate >= ISNULL(@startDate, MyTable.StartDate)
AND MyTable.EndDate <= ISNULL(@startDate, MyTable.EndDate)