我遇到以下问题。我有一份系统每小时/每天运行的检查清单。它知道要运行的检查,因为它们在数据库中。现在,我制作了一张不同的表,可以在其中为每个应用程序设置维护时段。我正在运行以下问题。
我加入了有关应用程序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时强制某个日期,但是应该有一个更清洁的选项对吧?
答案 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]);