Reputation: 15965
I have lots of employee holiday records which show the holiday start and end days. I need to work out how many holidays each employee has taken between 2 dates, i.e. 2015-01-01 00:00:00
to 2015-02-01 00:00:00
.
How do I deal with holidays where the holiday starts before that range or ends after that range?
For example, if employee 1
took off 2015-01-10
to 2015-01-15
, that's fine as 5 days holiday
But if employee 2
took off 2015-12-25
to 2015-01-05
, that should only count as 5 days holiday
The same for the other side, i.e. if employee 3
took off 2015-01-25
to 2015-02-05
, that should only count as 5 days holiday
Upvotes: 0
Views: 843
Reputation: 10700
Say your employee holiday table looks like this:
CREATE TABLE EmployeeHoliday (
EmployeeId INT,
HolidayStart DATETIME,
HolidayEnd DATETIME
)
The following query returns the number of days per employee, between the two specified dates (variables):
DECLARE @CountFromDate AS DATETIME = '2015-01-01'
DECLARE @CountToDate AS DATETIME = '2015-02-01'
SELECT EmployeeId,
SUM(DATEDIFF(DAY,
CASE WHEN @CountFromDate < HolidayStart THEN HolidayStart ELSE @CountFromDate END,
CASE WHEN @CountToDate > HolidayEnd THEN HolidayEnd ELSE @CountToDate END
)
) AS HolidaysHeld
FROM EmployeeHoliday
GROUP BY EmployeeId
If you don't want this query to output employees that only had holidays outside the specified interval of time, include the following WHERE
-clause just before the GROUP BY
part of the query:
WHERE HolidayStart <= @CountToDate AND HolidayEnd >= @CountFromDate
Upvotes: 1
Reputation: 1827
declare @datebeg datetime = '20150101', @dateend datetime = '20150201'
select e.employeeid, sum(datediff(day, case when @datebeg < h.datebeg then h.datebeg else @datebeg end,
case when @dateend > h.dateend then h.dateend else @dateend end))
from holiday h
where @datebeg <= h.dateend and @dateend >= h.datebeg
group by h.employeeid
Upvotes: 0
Reputation: 1271003
You use date logic. Other databases have least()
and greatest()
functions to help with this. In SQL Server, you can use somewhat more complicated case
statements. The result is something like this:
select h.employee_id,
sum(datediff(day,
(case when h.start < @StartDate then @StartDate else h.start end),
(case when h.end > @EndDate then @EndDate else h.end end)
)
) as DaysOnHoliday
from holidays h
where h.start <= @EndDate and h.end >= @StartDate
group by h.employee_id
Upvotes: 1