It looks like you're already using this trick to get the working days (i.e. excluding weekends) between two dates.
NB: This solution assumes that the session's language is English, and that Saturday and Sunday are considered non-working days; these assumptions may not be true for all cultures.
From this post it seems you're already on the right track for excluding bank holidays. i.e.
DECLARE @StartDate DATETIME = '2016-09-01'
DECLARE @EndDate DATETIME = '2016-09-30'
DECLARE @TotalDays INT, @WorkDays INT
SELECT
@TotalDays = (DATEDIFF(dd, @StartDate, @EndDate) +1)
, @WorkDays =
(DATEDIFF(dd, @StartDate, @EndDate) + 1) --get the number of working days between 2 dates (including the date itself)
-(DATEDIFF(wk, @StartDate, @EndDate) * 2) --get the number of weekend days (i.e. 2 x number of weeks)
-(CASE WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN 1 ELSE 0 END) --\_then take into account if the current date fell over a weekend
-(CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN 1 ELSE 0 END) --/
- coalesce(
(
select count(1)
from BankHolidays
where HolidayDate between @StartDate and @EndDate
)
,0) --and remove any bank holidays which fall during this period
print @TotalDays
print @WorkDays
Note also that this assumes that all of the bank holidays in your table are against weekdays; not weekends (i.e. otherwise those days would be included twice).
- In the UK if a bank holiday falls on a weekend (e.g. Christmas this year is on a Sunday), that bank holiday is offset to the next working day (also taking into any other bank holidays; i.e. boxing day on 26th December is a bank holiday in the UK, so the Christmas bank holiday falls on 27th (or falls on 26th and Boxing day's offset to 27th, depending how you prefer to imagine it).
- However other cultures may behave differently. Also some people are expected to work weekends, so should the holiday normally fall on the weekend they may still get that as a holiday and not have the offset bank holiday instead; just to add more confusion).