sqlsql-servert-sqldatetimesql-server-2008-r2

Count just working days (exclude weekends and public holidays) and add filter that a query


I want to add a filter to a query which grabs dates till last 5 WORKING DAYS.

declare @DataRetentionPeriod INT =5
  Delete FROM dbo.table1 pt
   WHERE   CONVERT(varchar,pt.ptStampDateTime, 112) < CONVERT( VARCHAR, DATEADD(DAY, @DataRetentionPeriod * -1, GETDATE()), 112) 

So, I want to delete from table1 but want to retain data in that table till last 5 working days i.e., if the script runs on Monday then it should not count saturday and sunday in the filter and should delete records till last Friday - last weeks data should not be deleted. And if there is any public holiday in the last week then it should add move one more day back to keep 5 working days data.

I have a function which gives me last working day of the @date provided -

 select dbo.fn_previous_working_day(@date)

If the date is today - it will give yesterday If the date is a Monday - it will give Friday and if Friday was a holiday it will give Thursday

I have another function which gives NULL if the provided date is a working date and gives the details of the date if it a holiday/weekend

select dbo.fn_working_day(@date)

But I am just not able to find a way to add a filter to just count the last 5 working days (or whatever number is given in @dataretentionPeriod variable)

I even tried this to grab the last 5 working date

declare @i int =0, 
        @date datetime, 
        @newdate datetime, 
        @daten datetime = '2024-04-04', 
        @datet datetime
while @i  <5
Begin
select @date = convert(datetime,convert(varchar, dbo.fn_previous_working_day(@daten-@i),112))
select @datet = convert(datetime,convert(varchar, dbo.fn_previous_working_day(@date),112))
select @newdate = @datet
set @i = @i+1
end
select @newdate

But it gives me 27-04-2024 instead of 2024-04-26 as there are two public holidays in that week and the counter is only jumping by 1 day not 1 working day - how can i make the counter jump by 1 working day instead of 1 day

I am expecting the date filter to only consider 5 working days instead of just 5 days


Solution

  • If you can assume (should be fine for most countries) that the longest calendar span to consider is 10days in which we could always find 5 working days (you can adjust if not):

    with Seq as (
        select Offset 
        from (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) T (Offset)
    ), Last10Days as (
        select dateadd(day,-Offset, getdate()) as Dte
        from Seq
    )
    select top 5 *
    from Last10Days L10D
    where dbo.fn_working_day(Dte) is null 
    -- I simulated with this (I don't have your function)
    -- exists (select 1 as IsWeekDay where datename(weekday, L10D.Dte) not in ('Saturday', 'Sunday'))
    order by Dte desc
    

    We build a calendar of last 10days, and test all with your function, retaining the working days, then take the most recent 5