November 7, 2018 at 11:33 am
declare @EmpID int
select @EmpID = 3
;with AllEmployees as
(
select e.EmpID, e.EmpCode, e.ProperName, h.EffectiveStart,
EffectiveEnd = isnull(h.EffectiveEnd,'9999-12-30 00:00:00.000')
from z_Employees e
join z_ReportsToHistory h on e.EmpID = h.EmpID
where e.EmpID = @EmpID
union all
select e.EmpID, e.EmpCode, e.ProperName,
-- case statements ensure that the supervisor's date range overrides the employee's date range if the supervisor's range is more narrow
EffectiveStart = case when h.EffectiveStart < d.EffectiveStart then d.EffectiveStart else h.EffectiveStart end,
EffectiveEnd = case when isnull(h.EffectiveEnd,'9999-12-30 00:00:00.000') > isnull(d.EffectiveEnd,'9999-12-30 00:00:00.000')
then isnull(d.EffectiveEnd,'9999-12-30 00:00:00.000') else isnull(h.EffectiveEnd,'9999-12-30 00:00:00.000') end
from z_Employees e
join z_ReportsToHistory h on e.EmpID = h.EmpID
join AllEmployees d on h.ReportsToID = d.EmpID
)
select e.EmpID, t.PEDate,
DirectHours = sum(case when p.ProjectType = 1 then i.WorkHours else 0 end),
TotalHours = sum(i.WorkHours)
from AllEmployees e
join z_Timesheets t on e.EmpID = t.EmpID and t.PEDate between e.EffectiveStart and e.EffectiveEnd
join z_TimesheetItems i on t.TimeID = i.TimeID
join z_Projects p on i.ProjectID = p.ProjectID
group by e.EmpID, t.PEDate
order by e.EmpID, t.PEDate
November 7, 2018 at 12:07 pm
DBAless - Wednesday, November 7, 2018 11:33 AMAfter some more testing, I've found that my test data did not match my expected results, so I fixed the test data. Also, on the recursive section, it needed to compare the supervisor's effective end to the employee's effective end (similar to the effective start case statement). Here's where I've ended up. The case statements in the recursion were the key.
declare @EmpID int
select @EmpID = 3;with AllEmployees as
(
select e.EmpID, e.EmpCode, e.ProperName, h.EffectiveStart,
EffectiveEnd = isnull(h.EffectiveEnd,'9999-12-30 00:00:00.000')
from z_Employees e
join z_ReportsToHistory h on e.EmpID = h.EmpID
where e.EmpID = @EmpID
union all
select e.EmpID, e.EmpCode, e.ProperName,
-- case statements ensure that the supervisor's date range overrides the employee's date range if the supervisor's range is more narrow
EffectiveStart = case when h.EffectiveStart < d.EffectiveStart then d.EffectiveStart else h.EffectiveStart end,
EffectiveEnd = case when isnull(h.EffectiveEnd,'9999-12-30 00:00:00.000') > isnull(d.EffectiveEnd,'9999-12-30 00:00:00.000')
then isnull(d.EffectiveEnd,'9999-12-30 00:00:00.000') else isnull(h.EffectiveEnd,'9999-12-30 00:00:00.000') end
from z_Employees e
join z_ReportsToHistory h on e.EmpID = h.EmpID
join AllEmployees d on h.ReportsToID = d.EmpID
)
select e.EmpID, t.PEDate,
DirectHours = sum(case when p.ProjectType = 1 then i.WorkHours else 0 end),
TotalHours = sum(i.WorkHours)
from AllEmployees e
join z_Timesheets t on e.EmpID = t.EmpID and t.PEDate between e.EffectiveStart and e.EffectiveEnd
join z_TimesheetItems i on t.TimeID = i.TimeID
join z_Projects p on i.ProjectID = p.ProjectID
group by e.EmpID, t.PEDate
order by e.EmpID, t.PEDate
Reformatted your code and put semicolons where they belong, which is NOT in front of the WITH that defines a CTE. Semicolons are terminators not beginnators. They belong at the END of statements. As not terminating statements with a semicolon has been deprecated you should get in the habit of using them at the end of statements.
declare @EmpID int;
select @EmpID = 3;
with [AllEmployees]
as (select [e].[EmpID]
, [e].[EmpCode]
, [e].[ProperName]
, [h].[EffectiveStart]
, 'EffectiveEnd' = isnull([h].[EffectiveEnd], '9999-12-30 00:00:00.000')
from [z_Employees] as [e]
join [z_ReportsToHistory] as [h]
on [e].[EmpID] = [h].[EmpID]
where [e].[EmpID] = @EmpID
union all
select [e].[EmpID]
, [e].[EmpCode]
, [e].[ProperName]
-- case statements ensure that the supervisor's date range overrides the employee's date range if the supervisor's range is more narrow
, 'EffectiveStart' = case
when [h].[EffectiveStart] < [d].[EffectiveStart] then
[d].[EffectiveStart]
else
[h].[EffectiveStart]
end
, 'EffectiveEnd' = case
when isnull([h].[EffectiveEnd], '9999-12-30 00:00:00.000') > isnull(
[d].[EffectiveEnd]
, '9999-12-30 00:00:00.000'
) then
isnull([d].[EffectiveEnd], '9999-12-30 00:00:00.000')
else
isnull([h].[EffectiveEnd], '9999-12-30 00:00:00.000')
end
from [z_Employees] as [e]
join [z_ReportsToHistory] as [h]
on [e].[EmpID] = [h].[EmpID]
join [AllEmployees] as [d]
on [h].[ReportsToID] = [d].[EmpID]
)
select [e].[EmpID]
, [t].[PEDate]
, 'DirectHours' = sum( case
when [p].[ProjectType] = 1 then
.[WorkHours]
else
0
end
)
, 'TotalHours' = sum(.[WorkHours])
from [AllEmployees] as [e]
join [z_Timesheets] as [t]
on [e].[EmpID] = [t].[EmpID]
and [t].[PEDate]
between [e].[EffectiveStart] and [e].[EffectiveEnd]
join [z_TimesheetItems] as
on [t].[TimeID] = .[TimeID]
join [z_Projects] as [p]
on .[ProjectID] = [p].[ProjectID]
group by [e].[EmpID]
, [t].[PEDate]
order by [e].[EmpID]
, [t].[PEDate];
November 7, 2018 at 12:37 pm
Yeah, I have several habits I'll have to adjust when we upgrade from SQL Server 2014. Of course, the vendor application I'm "tweaking" has a ton of old code like raiserror that will need clean up if MS ever truly commits to all the things they say they are deprecating.
Thanks again for the help! Once you got me on the right path it wasn't as hard I was making out to be in my head. 🙂
January 28, 2019 at 9:13 am
--***************************************************************************************
-- Generate employee data
--***************************************************************************************
CREATE TABLE #Employee (
EmpID int NOT NULL,
EmpName nvarchar(255) NOT NULL);
Viewing 4 posts - 16 through 18 (of 18 total)
You must be logged in to reply to this topic. Login to reply