Вы можете сделать это без рекурсивного CTE, если вам нужны данные за один месяц.
- В первых 28 днях месяца 20 рабочих дней. Просто отметьте 29, 30 и 31
- В первые 7 дней 5 рабочих дней, 10 в 14 и т. Д. Просто проверьте 6 дней.
DECLARE @dt AS DATE = '2018-11-09';
WITH vars1 AS (
SELECT
d1 = DATEADD(dd, 1, EOMONTH(@dt, -1)),
dn = EOMONTH(@dt),
wks = DAY(@dt) / 7
), vars AS (
SELECT
d1, -- first day of month
dn, -- last day of month
wks, -- number of 7-day intervals elapsed
d29 = DATEADD(dd, 28, d1), -- 29th day of month
d30 = DATEADD(dd, 29, d1),
d31 = DATEADD(dd, 30, d1),
dp1 = DATEADD(dd, wks * 7 + 0, d1), -- wks * 7 gives you 0, 7, 14, 21 or 28
dp2 = DATEADD(dd, wks * 7 + 1, d1), -- wks * 7 + 0 ... 5 are the dates to check
dp3 = DATEADD(dd, wks * 7 + 2, d1),
dp4 = DATEADD(dd, wks * 7 + 3, d1),
dp5 = DATEADD(dd, wks * 7 + 4, d1),
dp6 = DATEADD(dd, wks * 7 + 5, d1)
FROM vars1
)
SELECT
[no. of business days] = 20 +
IIF(d29 <= dn AND DATENAME(dw, d29) NOT IN ('Saturday', 'Sunday'), 1, 0) +
IIF(d30 <= dn AND DATENAME(dw, d30) NOT IN ('Saturday', 'Sunday'), 1, 0) +
IIF(d31 <= dn AND DATENAME(dw, d31) NOT IN ('Saturday', 'Sunday'), 1, 0),
[no. of business days passed] = wks * 5 +
IIF(dp1 <= @dt AND DATENAME(dw, dp1) NOT IN ('Saturday', 'Sunday'), 1, 0) +
IIF(dp2 <= @dt AND DATENAME(dw, dp2) NOT IN ('Saturday', 'Sunday'), 1, 0) +
IIF(dp3 <= @dt AND DATENAME(dw, dp3) NOT IN ('Saturday', 'Sunday'), 1, 0) +
IIF(dp4 <= @dt AND DATENAME(dw, dp4) NOT IN ('Saturday', 'Sunday'), 1, 0) +
IIF(dp5 <= @dt AND DATENAME(dw, dp5) NOT IN ('Saturday', 'Sunday'), 1, 0) +
IIF(dp6 <= @dt AND DATENAME(dw, dp6) NOT IN ('Saturday', 'Sunday'), 1, 0)
FROM vars
DB Fiddle