SQL Server : get next relative day of week. (Next Monday, Tuesday, Wed…)

后端 未结 7 1327
青春惊慌失措
青春惊慌失措 2020-12-05 07:52

What I need is a date for the next given day (Monday, Tuesday, Wed...) following today\'s date.

The user is allowed to select what day following they want and that i

7条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-12-05 08:35

    It's an old question. But I'm sure that posting better solution worth it.

    -- 0 = 1st Mon, 1 = 1st Tue, 2 = 1st Wed, ..., 5 = 1st Sat, 6 = 1st Sun
    -- 7 = 2nd Mon, 8 = 2nd Tue, ...
    declare @NextDayID int = 0, @Date date = getdate()
    
    select cast (cast (
        -- last Monday before [Date] inclusive, starting from 1900-01-01
        datediff (day, @NextDayID % 7, @Date) / 7 * 7
        -- shift on required number of days
        + @NextDayID + 7
        as datetime) as date)
    

    This solution is improved solution of @Bogdan Sahlean. It can operate @NextDayID that is greater than 6. So you can, for example, find 2nd Monday from today.

    Following query shows that my solution works correctly.

    select [Date]
        , convert (char(5), [0], 10) as Mon1
        , convert (char(5), [1], 10) as Tue1
        , convert (char(5), [2], 10) as Wed1
        , convert (char(5), [3], 10) as Thu1
        , convert (char(5), [4], 10) as Fri1
        , convert (char(5), [5], 10) as Sat1
        , convert (char(5), [6], 10) as Sun1
        , convert (char(5), [7], 10) as Mon2
        , convert (char(5), [8], 10) as Tue2
    from (
        select [Date], NextDayID
            , cast (cast (
              datediff (day, NextDayID % 7, [Date]) / 7 * 7 -- last Monday before [Date] inclusive, starting from 1900-01-01
            + NextDayID + 7 -- shift on required number of days
            as datetime) as date) as NextDay
        from (
            select datefromparts (2018, 5, dt) as [Date]
            from (values(14),(15),(16),(17),(18),(19),(20))t_(dt)
        ) d
        cross join (values(0),(1),(2),(3),(4),(5),(6),(7),(8))nd(NextDayID)
    ) t
    pivot (
        min (NextDay) for NextDayID in ([0], [1], [2], [3], [4], [5], [6], [7], [8])
    ) pvt
    

    Result:

    Date       | Mon1  | Tue1  | Wed1  | Thu1  | Fri1  | Sat1  | Sun1  | Mon2  | Tue2
    -----------+-------+-------+-------+-------+-------+-------+-------+-------+------
    2018-05-14 | 05-21 | 05-15 | 05-16 | 05-17 | 05-18 | 05-19 | 05-20 | 05-28 | 05-22
    2018-05-15 | 05-21 | 05-22 | 05-16 | 05-17 | 05-18 | 05-19 | 05-20 | 05-28 | 05-29
    2018-05-16 | 05-21 | 05-22 | 05-23 | 05-17 | 05-18 | 05-19 | 05-20 | 05-28 | 05-29
    2018-05-17 | 05-21 | 05-22 | 05-23 | 05-24 | 05-18 | 05-19 | 05-20 | 05-28 | 05-29
    2018-05-18 | 05-21 | 05-22 | 05-23 | 05-24 | 05-25 | 05-19 | 05-20 | 05-28 | 05-29
    2018-05-19 | 05-21 | 05-22 | 05-23 | 05-24 | 05-25 | 05-26 | 05-20 | 05-28 | 05-29
    2018-05-20 | 05-21 | 05-22 | 05-23 | 05-24 | 05-25 | 05-26 | 05-27 | 05-28 | 05-29
    

    This solution doesn't depend on @@datefirst.

提交回复
热议问题