We have a table that contains a snapshot of every employees data at the end of each month until the month they leave the company. This table also has the snapshot of each employee for the current day which is replaced each day until the end of the month.
What we're trying to do is select weekly statistics for Hires, Rehires, and Terms for each department. However since we only capture data by month and not by week, I'm having trouble breaking this down by week without getting duplicates.
I'm able to pull monthly statistics similar to this. Is there a method to group by each week in a month if there is only an entry for a month?
select
Max(AsOfDate) as AsOfDate,
Sector,
Department,
sum(case
when DatePart(Year, TermDate) = DatePart(Year, AsOfDate) and DatePart(Month, TermDate) = DatePart(Month, AsOfDate) then 1
else 0
end) as Terms,
sum(case
when DatePart(Year, HireDate) = DatePart(Year, AsOfDate) and DatePart(Month, HireDate) = DatePart(Month, AsOfDate) then 1
else 0
end) as Hires,
sum(case
when DatePart(Year, RehireDate) = DatePart(Year, AsOfDate) and DatePart(Month, RehireDate) = DatePart(Month, AsOfDate) then 1
else 0
end) as Rehires
from Employee_History
group by Year(AsOfDate), datepart(Month, AsOfDate), Department
Example data if today was 2022-03-17
AsOfDate | EmployeeID | Department | Title | HireDate | RehireDate | TermDate |
---|---|---|---|---|---|---|
2022-01-31 | EMP22 | HR | Admin | 2021-01-12 | null | 2022-01-17 |
2022-01-31 | EMP45 | IT | Programmer | 2022-01-10 | null | null |
2022-02-28 | EMP45 | IT | Programmer | 2022-01-10 | null | null |
2022-03-17 | EMP45 | IT | Programmer | 2022-01-10 | null | null |
2022-01-31 | EMP03 | IT | Manager | 2018-08-17 | 2022-01-24 | null |
2022-02-28 | EMP03 | IT | Manager | 2018-08-17 | 2022-01-24 | null |
2022-03-17 | EMP03 | IT | Manager | 2018-08-17 | 2022-01-24 | null |
Desired output for January 2022 for example
AsOfDate | Department | Hires | Rehires | Terms |
---|---|---|---|---|
2022-01-01 | HR | 0 | 0 | 0 |
2022-01-08 | HR | 0 | 0 | 0 |
2022-01-15 | HR | 0 | 0 | 0 |
2022-01-22 | HR | 0 | 0 | 1 |
2022-01-29 | HR | 0 | 0 | 0 |
2022-01-01 | IT | 0 | 0 | 0 |
2022-01-08 | IT | 0 | 0 | 0 |
2022-01-15 | IT | 1 | 0 | 0 |
2022-01-22 | IT | 0 | 0 | 0 |
2022-01-29 | IT | 0 | 1 | 0 |
CodePudding user response:
What you need is a mapping table for week <-> end of the Month thing containing:
create table weekmap(asOfDate DATE PRIMARY KEY, weekDayStart DATE, weekDayEnd DATE)
One problem is that your snapshot table contains "current date" if month isn't finished. I would advice to change that so it always has end of month to simplify stuff. Alternatively, create new column for that.
Populate it with whatever logic your weeks should be, some use ISO WEEK, some use day from start of new year etc.
Then you join your snapshot against this table (and you need to handle case where asOfDate isn't end of the month):
select w.asOfDate, w.weekDayStart, t.Department
, SUM(case when HireDate between weekdaystart and weekdayend then 1 else 0 end) AS hires
, SUM(case when ReHireDate between weekdaystart and weekdayend then 1 else 0 end) AS rehires
, SUM(case when TermDate between weekdaystart and weekdayend then 1 else 0 end) AS term
from snapshottable t
inner join weekmap w
ON w.asOfDate = t.asOfDateFixedEndOfMonth
group by w.asOfDate, w.weekDayStart, t.Department
There will be some loss of data if a guy is hired and fired twice in one month, but then you probably have a bigger problem