Assuming that NationalHolidayIndicator
or NationalHoliday
are already in your date table, use a correlated subquery.
SELECT d.[Date]
, d.NationalHolidayIndicator
--, d.NationalHoliday
, (SELECT MAX([Date])
FROM [Date]
WHERE [Date] < d.[Date]
AND DATENAME(WEEKDAY, d.[Date]) NOT IN ('Saturday', 'Sunday')
AND d.NationalHolidayIndicator = 'no'
--AND d.NationalHoliday IS NULL
) as PreviousBusinessDay
FROM [Date] d
If you don't already have NationalHolidayIndicator
and NationalHoliday
, For the U.S. that might look something like this:
case
when datepart(month, dt) = 1 and datepart(day, dt) = 1 and datepart(weekday, dt) between 2 and 6 then 'yes'
when datepart(month, dt) = 1 and datepart(day, dt) = 2 and datepart(weekday, dt) = 2 then 'yes'
when datepart(month, dt) = 12 and datepart(day, dt) = 31 and datepart(weekday, dt) = 6 then 'yes'
when datepart(month, dt) = 1 and datepart(day, dt) between 15 and 21 and datepart(weekday, dt) = 2 and datepart(year, dt) > 1985 then 'yes'
when datepart(month, dt) = 2 and datepart(day, dt) between 15 and 21 and datepart(weekday, dt) = 2 then 'yes'
when datepart(month, dt) = 5 and datepart(day, dt) > 24 and datepart(weekday, dt) = 2 then 'yes'
when datepart(month, dt) = 7 and datepart(day, dt) = 4 and datepart(weekday, dt) between 2 and 6 then 'yes'
when datepart(month, dt) = 7 and datepart(day, dt) = 5 and datepart(weekday, dt) = 2 then 'yes'
when datepart(month, dt) = 7 and datepart(day, dt) = 3 and datepart(weekday, dt) = 6 then 'yes'
when datepart(month, dt) = 9 and datepart(day, dt) between 1 and 7 and datepart(weekday, dt) = 2 then 'yes'
when datepart(month, dt) = 10 and datepart(day, dt) between 8 and 14 and datepart(weekday, dt) = 2 then 'yes'
when datepart(month, dt) = 11 and datepart(day, dt) = 11 and datepart(weekday, dt) between 2 and 6 then 'yes'
when datepart(month, dt) = 11 and datepart(day, dt) = 12 and datepart(weekday, dt) = 2 then 'yes'
when datepart(month, dt) = 11 and datepart(day, dt) = 10 and datepart(weekday, dt) = 6 then 'yes'
when datepart(month, dt) = 11 and datepart(day, dt) between 22 and 28 and datepart(weekday, dt) = 5 then 'yes'
when datepart(month, dt) = 12 and datepart(day, dt) = 25 and datepart(weekday, dt) between 2 and 6 then 'yes'
when datepart(month, dt) = 12 and datepart(day, dt) = 26 and datepart(weekday, dt) = 2 then 'yes'
when datepart(month, dt) = 12 and datepart(day, dt) = 24 and datepart(weekday, dt) = 6 then 'yes'
else 'no'
end as NationalHolidayIndicator
, case
when datepart(month, dt) = 1 and datepart(day, dt) = 1 then 'New Year''s Day'
when datepart(month, dt) = 1 and datepart(day, dt) = 2 and datepart(weekday, dt) = 2 then 'New Year''s Day - legal'
when datepart(month, dt) = 12 and datepart(day, dt) = 31 and datepart(weekday, dt) = 6 then 'New Year''s Day - legal'
when datepart(month, dt) = 1 and datepart(day, dt) between 15 and 21 and datepart(weekday, dt) = 2 and datepart(year, dt) > 1985 then 'Martin Luther King Day'
when datepart(month, dt) = 2 and datepart(day, dt) between 15 and 21 and datepart(weekday, dt) = 2 then 'Presidents'' Day'
when datepart(month, dt) = 5 and datepart(day, dt) > 24 and datepart(weekday, dt) = 2 then 'Memorial Day'
when datepart(month, dt) = 7 and datepart(day, dt) = 4 then 'Independence Day'
when datepart(month, dt) = 7 and datepart(day, dt) = 5 and datepart(weekday, dt) = 2 then 'Independence Day - legal'
when datepart(month, dt) = 7 and datepart(day, dt) = 3 and datepart(weekday, dt) = 6 then 'Independence Day - legal'
when datepart(month, dt) = 9 and datepart(day, dt) between 1 and 7 and datepart(weekday, dt) = 2 then 'Labor Day'
when datepart(month, dt) = 10 and datepart(day, dt) between 8 and 14 and datepart(weekday, dt) = 2 then 'Columbus Day'
when datepart(month, dt) = 11 and datepart(day, dt) = 11 then 'Veterans Day'
when datepart(month, dt) = 11 and datepart(day, dt) = 12 and datepart(weekday, dt) = 2 then 'Veterans Day - legal'
when datepart(month, dt) = 11 and datepart(day, dt) = 10 and datepart(weekday, dt) = 6 then 'Veterans Day - legal'
when datepart(month, dt) = 11 and datepart(day, dt) between 22 and 28 and datepart(weekday, dt) = 5 then 'Thanksgiving Day'
when datepart(month, dt) = 11 and datepart(day, dateadd(day, -1, dt)) between 22 and 28 and datepart(weekday, dateadd(day, -1, dt)) = 5 and datepart(year, dt) between 1977 and 2013 then 'Thanksgiving, Day After'
when datepart(month, dt) = 11 and datepart(day, dateadd(day, -1, dt)) between 22 and 28 and datepart(weekday, dateadd(day, -1, dt)) = 5 and datepart(year, dt) > 2014 then 'Native American Heritage Day'
when datepart(month, dt) = 12 and datepart(day, dt) = 25 then 'Christmas Day'
when datepart(month, dt) = 12 and datepart(day, dt) = 26 and datepart(weekday, dt) = 2 then 'Christmas Day - legal'
when datepart(month, dt) = 12 and datepart(day, dt) = 24 and datepart(weekday, dt) = 6 then 'Christmas Day - legal'
end as NationalHoliday
...although my holiday names and dates are from my State laws, not Federal laws.