Очевидно, что я неправильно прочитал вопрос, но я оставлю его здесь на случай, если кто-то еще может счесть его образовательным (это также демонстрирует, как результат DATEPART( dw, ... )
может отличаться в зависимости от сервера, поэтому жесткие значения, как в приведенном выше ответе, могут привести к ошибочным результатам). результаты в зависимости от среды) - при этом будет рассчитана ближайшая дата к указанному дню недели (тогда как вопрос, заданный для предыдущего вторника, в частности) ...
Тебе дали свидание. Вы хотите найти ближайший вторник, поэтому сначала вам нужно выяснить, какой день недели представляет данная дата. Google "mssql day of week" и first hit - это функция, которую вы можете использовать для получения дня недели. Он будет в целочисленном формате, поэтому вам нужно будет указать , какие числа соответствуют дням недели .
Результат будет основан на значении @@ DATEFIRST, которое определяет первый день недели (а результаты представляют собой единичный индекс), поэтому вам необходимо настроить целевое значение дня недели, чтобы оно соответствовало значение @@DATEFIRST
сервера. Вы можете сделать это, вычтя @@DATEFIRST
из 7
, добавив целевое значение дня недели (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
Результаты: