Диапазон дат можно построить с помощью CTE, после чего вы можете СОЕДИНИТЬ свои отсутствия с датами, которые попадают в пределы отсутствия. Затем просто посчитайте эти даты и сгруппируйте их по году и месяцу даты.
Я узнал, как преобразовать номер вашего месяца в текст. Вы можете взять ЛЕВЫЙ (..., 3) из этого, если хотите.
WITH DATRANGE AS (SELECT MIN((FromDate)) as startDate, max(ToDate) endDate From Test),
YourCal AS (SELECT startDate d FROM DATRANGE
UNION ALL
SELECT DATEADD(day,1,d) d FROM YourCal, DATRANGE WHERE d < enddate
)
SELECT T.empid,
YEAR(Y.d),
DATENAME(month, DATEADD(month, MONTH(y.d)-1, CAST('2008-01-01' AS datetime))) As M,
COUNT(1) As DayCount
FROM TEST T JOIN
YourCal Y
ON Y.d BETWEEN FromDate AND ToDate
GROUP BY T.empid,YEAR(Y.d),DATENAME(month, DATEADD(month, MONTH(y.d)-1, CAST('2008-01-01' AS datetime))),MONTH(y.d)
ORDER BY empid, YEAR(y.d), MONTH(y.d)
option (maxrecursion 0);
с метками из 3 буквенных месяцев, это будет
WITH DATRANGE AS (SELECT MIN((FromDate)) as startDate, max(ToDate) endDate From Test),
YourCal AS (SELECT startDate d FROM DATRANGE
UNION ALL
SELECT DATEADD(day,1,d) d FROM YourCal, DATRANGE WHERE d < enddate
)
SELECT T.empid,
YEAR(Y.d) Yr,
LEFT(DATENAME(month, DATEADD(month, MONTH(y.d)-1, CAST('2008-01-01' AS datetime))),3) As M,
COUNT(1) As DayCount
FROM TEST T JOIN
YourCal Y
ON Y.d BETWEEN FromDate AND ToDate
GROUP BY T.empid,
YEAR(Y.d),
LEFT(DATENAME(month, DATEADD(month, MONTH(y.d)-1, CAST('2008-01-01' AS datetime))),3),
MONTH(y.d)
ORDER BY empid, YEAR(y.d), MONTH(y.d)
option (maxrecursion 0);