我有一个SSRS报告,其中包括开始和结束日期参数。 对于开始日期和结束日期,可以设置选项 NULL。 规则是,如果开始日期为 null,则检索的数据从时间开始。 如果结束日期为 null,则将其设置为今天的日期。 这就是我在这里尝试做的事情:
SELECT *
FROM mytab
WHERE (Start >= CASE @From
WHEN NULL
THEN DATEADD(year, -100, @From)
END)
AND (End <= CASE @To
WHEN NULL THEN GETDATE()
END)
作为测试,我在查询中声明变量@From和@To,将它们设置为 NULL 并在 SSMS 上运行它。
我想实现的是说如果@From为空,则将值设置为 100 年前,并将其与 mytab 字段"开始"进行比较。同样,如果@To为 null,请将其设置为今天的日期并与"结束"进行比较。 但是,这不会返回任何数据。 这显然是错误的,那么正确的方法是什么?
这里不需要使用 CASE 语句,因为我们可以使用 ISNULL 或 COALESCE。
SELECT *
FROM mytab
WHERE Start >= ISNULL( @From , DATEADD(year, -100, GETDATE()) )
AND End <= ISNULL( @To , GETDATE() )
CASE 语法不会像您想要的那样解析 NULL。
DECLARE @TEST AS VARCHAR(10)
SET @TEST = NULL
SELECT CASE WHEN @TEST IS NULL THEN 1 ELSE 0 END AS TEST1,
CASE @TEST WHEN NULL THEN 1 ELSE 0 END AS TEST2
TEST1 的结果为 1,TEST2 的结果为 0 - 而不是预期的 1 和 1。
SELECT * from mytab WHERE (Start >= CASE WHEN @From IS NULL THEN DATEADD(year, -100, @From) END)
AND (End <= CASE WHEN @To IS NULL THEN GETDATE() END)
一个简单的case
表达式when
子句不能匹配null
,但你可以在搜索的case
中使用is null
来测试它:case when @From is NULL then Cast( '1900-01-01' as Date ) else @From end
。请注意,如果when
子句都不匹配,则else
子句将提供一个值。
针对您的问题的一个更整洁的解决方案是使用Coalesce
:
select *
from MyTab
where Coalesce( @From, Cast( '1900-01-01' as Date ) ) <= [Start] and
[End] <= Coalesce( @To, Cast( GetDate() as Date ) );
请注意,该值被强制转换为date
以消除一天中的时间。