SQL Server Find next woking date from the given data

cgvd09ve  于 2023-10-15  发布在  其他
关注(0)|答案(3)|浏览(107)

I have 2 columns named Userid and holidaydate in a table named userdays. Below is the data.
| Userid | holidaydate |
| ------------ | ------------ |
| 1 | 2023-01-17 |
| 1 | 2023-03-21 |
| 1 | 2023-03-22 |
| 1 | 2023-03-23 |
| 1 | 2023-05-12 |
| 2 | 2023-09-15 |
| 3 | 2023-06-09 |
| 3 | 2023-06-28 |

For each user, we have to find next working day. For 2023-01-17 next work date is 2023-01-18. For 2023-03-21 next work date is 2023-03-24 because 2023-03-22 and 2023-03-23 is a holiday

I need a sql query for below output:
| Userid | nextworkdate |
| ------------ | ------------ |
| 1 | 2023-01-18 |
| 1 | 2023-03-24 |
| 1 | 2023-03-24 |
| 1 | 2023-03-24 |
| 1 | 2023-05-13 |
| 2 | 2023-09-16 |
| 3 | 2023-06-10 |
| 3 | 2023-06-29 |

bjp0bcyl

bjp0bcyl1#

You could do a window function solution to get the next workday:

select *
,   COALESCE(nextnonholiday, min(nextnonholiday) over(partition by userid order by holidaydate rows between 1 following and unbounded following), dateadd(day, 1, holidaydate)) as nextWorkDay
from (
    select *, case when lead(holidaydate) over(partition by userid order by holidaydate) <> dateadd(day, 1, holidaydate) then dateadd(day, 1, holidaydate) end as nextNonHoliday
    from (
        VALUES  (1, N'2023-01-17')
        ,   (1, N'2023-03-21')
        ,   (1, N'2023-03-22')
        ,   (1, N'2023-03-23')
        ,   (1, N'2023-05-12')
        ,   (2, N'2023-09-15')
        ,   (3, N'2023-06-09')
        ,   (3, N'2023-06-28')
    ) t (Userid,holidaydate)
    ) x
order by userid, holidaydate

First you check if next non-holiday is same as next day, if not that's the value we want, otherwise we go to the next step.

In the next step, we get the first non-holiday date that we previously calculated in a "following" window function, ie. we basically look ahead and take the first non-holiday date from the table.

0ve6wy6x

0ve6wy6x2#

If weekends and business holidays don't interest you, this might be helpful :

with c1 as (
  select Userid, holidaydate, DATEADD(day, 1, holidaydate) as nextdate
  from mytable
),
c2 as (
  select Userid, nextdate
  from c1
  where nextdate not in (
    select distinct holidaydate
    from c1
  )
)
select Userid, (
        SELECT
            MIN(c2.nextdate)
        FROM c2
        WHERE c2.nextdate >= c1.nextdate
            AND c1.Userid = c2.Userid
    ) AS nextworkdate
from c1

Explanations :

C1 retrieves the nextdate by adding 1 day to the holidaydate .

C2 retrieves potential nextworkdate by excluding holidays.

Results :

Userid  nextworkdate
1       2023-01-18
1       2023-03-24
1       2023-03-24
1       2023-03-24
1       2023-05-13
2       2023-09-16
3       2023-06-10
3       2023-06-29

Demo here

kxeu7u2r

kxeu7u2r3#

Try this

with cte as
(

    SELECT
        (FORMAT(nextworkdate, 'ddd')) as days, nextworkdate
    from Table_1
) 
  select 
  case 
    when cte.days='sat' or cte.days='sun' then DATEADD(DAY, 2, nextworkdate)
  else DATEADD(DAY, 1, nextworkdate)
  end 
  from cte

相关问题