【发布时间】:2019-02-13 10:42:03
【问题描述】:
如何仅在 SQL Server 中查找给定日期前最近的星期二?
例如:今天是2018-09-09,结果应该是2018-09-04。
【问题讨论】:
标签: sql sql-server sql-server-2008 sql-server-2005
如何仅在 SQL Server 中查找给定日期前最近的星期二?
例如:今天是2018-09-09,结果应该是2018-09-04。
【问题讨论】:
标签: sql sql-server sql-server-2008 sql-server-2005
请试一试。
select
case when datepart(dw,getdate()) =7
or datepart(dw,getdate()) =6
or datepart(dw,getdate()) =5
or datepart(dw,getdate()) =4
then DATEADD(day, 3-datepart(dw,getdate()) , getdate())
else DATEADD(day, -4-datepart(dw,getdate()) , getdate())
end;
【讨论】:
显然我误读了这个问题,但我会把它留在这里以防其他人可能会发现它具有教育意义(它还演示了 DATEPART( dw, ... ) 结果如何因服务器而异,因此上述答案中的硬编码值可能会导致错误结果取决于环境) - 这将计算最接近指定星期几的日期(而问题是针对上一个星期二提出的,具体而言)...
给你一个约会。您想找到最近的星期二,因此您首先需要确定给定日期代表一周中的哪一天。 Google "mssql day of week" 和 first hit 是您可以用来获取星期几的函数。它将采用整数格式,因此您需要引用 which numbers represents which days of the week。
结果将基于定义一周的第一天的@@DATEFIRST 的值(结果是从一个开始的索引),因此您需要调整目标星期几的值以与服务器的@@DATEFIRST 值。您可以通过从7 中减去@@DATEFIRST 来做到这一点,添加目标星期几值(1:星期一到 7:星期日),将结果与 7 取模并添加 1 以保持从一开始索引:
( 7 - @@DATEFIRST + @targetDayOfWeek ) % 7 + 1
一旦您知道您的目标日期是星期几以及星期二代表的数字,您就可以计算天数差。如果幅度大于 3,则通过加减 7 进行调整以适应范围 [-3, 3]。
create function dbo.CalculateClosestDayOfWeekDate
(
@fromDate DATETIME,
@targetDayOfWeek int -- 1: Monday ... 7: Sunday
)
returns DATETIME
as
begin
-- AdjustedTargetDayOfWeek: ( 7 - @@DATEFIRST + @targetDayOfWeek ) % 7 + 1
-- FromDateDayOfWeek: DATEPART( dw, @fromDate )
-- DayOfWeekDiff = AdjustedTargetDayOfWeek - FromDateDayOfWeek
declare @daysToAdd int
set @daysToAdd = ( ( 7 - @@DATEFIRST + @targetDayOfWeek ) % 7 + 1 ) - DATEPART( dw, @fromDate )
-- if the nearest previous day-of-week is all that's wanted,
-- replace the below block with `if( 0 < @daysToAdd)`
-- and subtract 7 from @daysToAdd if true
if( 3 < ABS( @daysToAdd ) ) -- if magnitude greater than 3
begin
if( 3 < @daysToAdd ) -- if positive, subtract 7
begin
set @daysToAdd = @daysToAdd - 7
end
else -- negative, so add 7
begin
set @daysToAdd = @daysToAdd + 7
end
end
return DATEADD( day, @daysToAdd, @fromDate )
end
go
declare @testData table
(
FromDate dateTime,
TargetDayOfWeek int
)
insert @testData values ( '2018-09-08', 2 ) -- target Tuesday from a Saturday
insert @testData values ( '2018-09-08', 3 ) -- target Wednesday from a Saturday
insert @testData values ( '2018-09-09', 3 ) -- target Wednesday from a Sunday
insert @testData values ( '2018-09-09', 4 ) -- target Thursday from a Sunday
insert @testData values ( '2018-09-10', 4 ) -- target Thursday from a Monday
insert @testData values ( '2018-09-10', 5 ) -- target Friday from a Monday
select
td.FromDate
, td.TargetDayOfWeek
, dbo.CalculateClosestDayOfWeekDate( td.FromDate, td.TargetDayOfWeek ) ResultingDate
from
@testData td
结果:
【讨论】:
使用case when 和datepart 函数并有条件地查找最近的星期二
select case datepart(dw,getdate()) when 7 then DATEADD(day, -4, getdate())
when 1 then DATEADD(day, -5, getdate())
when 2 then DATEADD(day, -6, getdate())
when 3 then DATEADD(day, -7, getdate())
when 4 then DATEADD(day, -1, getdate())
when 5 then DATEADD(day, -2, getdate())
when 6 then DATEADD(day, -3, getdate())
else getdate() end;
【讨论】:
DATEPART( dw, ... ) 结果基于@@DATEFIRST 的值;不应该假设7 是本周的开始。通过( 7 - @@DATEFIRST + @targetDayOfWeek ) % 7 + 1 调整,其中@targetDayOfWeek 是2 周二