SQL NOT日期之间(包括NULL)

时间:2020-05-27 13:02:55

标签: sql tsql between

我遇到以下问题。我有一份系统每小时/每天运行的检查清单。它知道要运行的检查,因为它们在数据库中。现在,我制作了一张不同的表,可以在其中为每个应用程序设置维护时段。我正在运行以下问题。

我加入了有关应用程序ID的维护窗口表。像这样:

Select check.appid, check.query, maint.appid 
from checks as check 
left join maintenance as maint on maint.appid = check.appid

此后,我想添加一个where子句,最后得到以下内容

Select check.appid, check.query, maint.appid 
from checks as check 
left join maintenance as maint on maint.appid = check.appid

WHERE
SYSDATETIMEOFFSET()
            BETWEEN 
            CONVERT(DATETIMEOFFSET,maint.StartDateTime AT TIME ZONE maint.[TimeZone]) 
            AND 
            CONVERT(DATETIMEOFFSET,maint.EndDateTime AT TIME ZONE maint.[TimeZone]);

这将返回一个列表,其中包含当前正在维护的应用程序,因此不应运行检查。

我尝试将其设为“ NON BETWEEN”。但这使我最终根本没有任何记录,因为没有维护时,开始和结束日期将在联接上返回null。

一个肮脏的解决方法可能是强制在1990年或在日期为null时强制某个日期,但是应该有一个更清洁的选项对吧?

2 个答案:

答案 0 :(得分:1)

我认为您希望将条件移至ON子句:

select c.appid, c.query, m.appid 
from checks c left join
     maintenance m
     on m.appid = c.appid and
        SYSDATETIMEOFFSET() not between 
            CONVERT(DATETIMEOFFSET, maint.StartDateTime AT TIME ZONE maint.[TimeZone]) AND
            CONVERT(DATETIMEOFFSET,maint.EndDateTime AT TIME ZONE maint.[TimeZone]);

这将返回checks中的所有行以及来自maintenance的相应 active 信息。

答案 1 :(得分:0)

从查询的角度来看,结果将是检查表中的所有行,而仅是维护表中与appid匹配的行。

如果只需要维护中的检查,则只需将联接更改为内部联接。还是我误会了?

Select check.appid, check.query, maint.appid 
from checks as check 
**inner** join maintenance as maint on maint.appid = check.appid

WHERE
SYSDATETIMEOFFSET()
            BETWEEN 
            CONVERT(DATETIMEOFFSET,maint.StartDateTime AT TIME ZONE maint.[TimeZone]) 
            AND 
            CONVERT(DATETIMEOFFSET,maint.EndDateTime AT TIME ZONE maint.[TimeZone]);

如果要进行所有检查,并且仅维护中的那些行位于日期范围内,则可以将IS NULL附加到where子句

Select check.appid, check.query, maint.appid 
from checks as check 
left join maintenance as maint on maint.appid = check.appid

WHERE
**maint.appid IS NULL OR**
SYSDATETIMEOFFSET()
            BETWEEN 
            CONVERT(DATETIMEOFFSET,maint.StartDateTime AT TIME ZONE maint.[TimeZone]) 
            AND 
            CONVERT(DATETIMEOFFSET,maint.EndDateTime AT TIME ZONE maint.[TimeZone]);