SQL Server 查找接近服务日期和月份的行
Posted
技术标签:
【中文标题】SQL Server 查找接近服务日期和月份的行【英文标题】:SQL Server find rows approaching a service day and month 【发布时间】:2020-11-13 00:05:51 【问题描述】:我有一张表格,其中列出了带有安装日期的设备。这些物品需要每年或每五年保养一次。因此,这些行的服务间隔为 1 或 5。类似于:
CREATE TABLE Equipment(
Guid uniqueidentifier,
InstallationDate datetime,
ServiceInterval tinyint
);
我需要做的是在设备到期前两个月返回一份设备清单
为简单起见,假设我有这些安装日期,并且它们的服务间隔均为 1,这意味着需要每年进行一次服务。
2008-1-17
2011-4-28
2012-5-13
2020-9-6
2006-12-2
我需要从这个列表中返回那些(忽略年份)日期和月份属于接下来两个月的列表。所以第一个和最后一个项目需要服务。第一项需要在 1 月维修,最后一项在 12 月维修。
我不确定解决此问题的最佳方法。当然这一定是一个常见的要求,但我找不到任何可以学习的例子。我可以轻松找到范围之间的日期,但很难解决这个问题。
有人能指点我正确的方向吗?
更新:2020 年 11 月 15 日
经过一番思考和尝试其他人提出的建议后,我想出了以下脚本。我意识到这些设备大部分是灭火器,每年都需要维修。他们还需要每 5 年和 10 年提供一次扩展服务。我需要一份即将用于这些服务的资产清单。
select top 20
MONTH(InstallationDate) as InstallMonth,
Day(InstallationDate) as InstallDay,
format(InstallationDate,'MMM dd yyyy') as Installed,
case WHEN DATEFROMPARTS(year(getdate()),month(InstallationDate),day(InstallationDate)) < getdate()
then dateadd(year,1, DATEFROMPARTS(year(getdate()),month(InstallationDate),day(InstallationDate)) )
else DATEFROMPARTS(year(getdate()),month(InstallationDate),day(InstallationDate))
end as ServiceDue,
case when year(InstallationDate) + 5 = year(getdate()) then '5 year service due'
when year(InstallationDate) + 5 < year(getdate()) then '5 year service passed'
when year(InstallationDate) + 5 > year(getdate()) then 'Five year service due ' + cast(year(InstallationDate) + 5 as varchar)
end as '5 Year Service',
case when year(InstallationDate) + 10 = year(getdate()) then '10 year service due'
when year(InstallationDate) + 10 < year(getdate()) then '10 year service passed'
when year(InstallationDate) + 10 > year(getdate()) then 'Ten year service due ' + cast(year(InstallationDate) + 10 as varchar)
end as '10 Year Service'
from equipment e
order by
case WHEN DATEFROMPARTS(year(getdate()),month(InstallationDate),day(InstallationDate)) < getdate()
then dateadd(year,1, DATEFROMPARTS(year(getdate()),month(InstallationDate),day(InstallationDate)) )
else DATEFROMPARTS(year(getdate()),month(InstallationDate),day(InstallationDate))
end asc
【问题讨论】:
【参考方案1】:可以使用 GETDATE 作为 CURR_START_DT 以及使用 EOMONTH(GETDATE(), 2) 作为 CURR_END_DT 来计算即将到来的 2 个月日期窗口。截至今天的日期窗口是 CURR_START_DT ='2020-11-13' 和 CURR_END_DT='2021-01-31'。由于年份无关紧要,而且日期窗口可能跨越 1 年以上,因此 CALC_DT 是使用 CURR_START_DT 中的 YEAR 创建的,而 PLUS_CALC_DT 是使用 CURR_END_DT 中的 YEAR 创建的。像这样的
声明表并查询
declare @YourTable table(InstallationDate date);
insert into @YourTable values
('2008-1-17')
,('2011-4-28')
,('2012-5-13')
,('2020-9-6')
,('2006-12-2');
select yt.InstallationDate, dfp.calc_dt, dfp_plus.calc_dt as plus_calc_dt,
dfp.dt as curr_start_dt, dfp.eom as curr_end_dt
from @YourTable yt
cross apply
(select cast(getdate() as date) dt, eomonth(getdate(), 2) eom,
datefromparts(year(getdate()),
month(yt.InstallationDate),
day(yt.InstallationDate)) calc_dt) dfp
cross apply
(select datefromparts(year(dfp.eom),
month(yt.InstallationDate),
day(yt.InstallationDate)) calc_dt) dfp_plus
where dfp.calc_dt between dfp.dt and dfp.eom
or
dfp_plus.calc_dt between dfp.dt and dfp.eom;
输出
InstallationDate calc_dt plus_calc_dt curr_start_dt curr_end_dt
2008-01-17 2020-01-17 2021-01-17 2020-11-13 2021-01-31
2006-12-02 2020-12-02 2021-12-02 2020-11-13 2021-01-31
【讨论】:
非常感谢。自从它首先出现以来,我将其标记为答案。【参考方案2】:根据要求,以下查询应该可以工作
SELECT
InstallationDate,
CONCAT(MONTH(InstallationDate),'-',DAY(InstallationDate)) as install_mmdd,
CONCAT(MONTH(DATEADD(MONTH,2,InstallationDate)),'-',DAY(DATEADD(MONTH,2,InstallationDate))) as next_svc_mmdd
FROM Equipment
WHERE MONTH(DATEADD(MONTH,2,InstallationDate)) <= 3
SQL Fiddle link
【讨论】:
非常有帮助的感谢和小提琴是一个很大的帮助。谢谢回答。我将较早的答案标记为答案只是因为它排在第一位。【参考方案3】:嗯。 . .我正在考虑构建下一个安装日期,然后只是做一个简单的比较:
select e.*
from equipment e cross apply
(values (case when month(installationdate) < month(getdate()) or
(month(installationdate) = month(getdate()) and
day(installationdate < day(getdate())
)
then datefromparts(year(getdate()) + 1, month(installationdate), day(installationdate))
else datefromparts(year(getdate()), month(installationdate), day(installationdate))
end)
) v(next_installationdate)
where next_installationdate < dateadd(month, -2, getdate())
【讨论】:
这有几个我修复的语法错误,但它没有返回任何数据。不过谢谢分享。以上是关于SQL Server 查找接近服务日期和月份的行的主要内容,如果未能解决你的问题,请参考以下文章