SQL Server: поиск ближайшего вторника - PullRequest
0 голосов
/ 08 сентября 2018

Как найти ближайший вторник по заданной дате, предшествующей только в SQL Server?

Пример: сегодня 2018-09-09, результат должен быть 2018-09-04.

Ответы [ 3 ]

0 голосов
/ 08 сентября 2018

Очевидно, что я неправильно прочитал вопрос, но я оставлю его здесь на случай, если кто-то еще может счесть его образовательным (это также демонстрирует, как результат 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

Результаты:

enter image description here

0 голосов
/ 03 января 2019

Пожалуйста, попробуйте.

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;
0 голосов
/ 08 сентября 2018

используйте функции 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...