我四处走动,无法弄清楚如何解决这个问题。我有2张桌子。一个包含每个员工/客户/周最多1个记录,列出他们将在该周工作的估计小时数。这是下表中列出的"预测活动"。另一个表列出了可计费活动。给定员工可以在一周内为给定客户提供多个可计费活动记录。这些列在表格" BillableActivities"中。
我正在尝试创建一个select语句,该语句将返回所有这些信息的摘要,如" Desired Output"下表,但有一些额外的聚合和过滤器。输出应该具有预测的小时数,作为所有可计费小时数的总和,其中批准= 1作为"小时到比尔"以及所有可计费小时的总和,其中批准= 0作为"计划小时&# 34。
我怀疑有一种比我所做的更直接的方式,但我已经非常接近了。我坚持的问题是,在某一周内,员工有预测时间但没有计费小时,反之亦然。为了帮助解决这个问题,我创建了一个Union,但是我知道这个特殊的联合将不会按预期工作,因为如果资源存在于该周的预测活动中,即使对于另一个客户,它也将从第二个语句中排除。我尝试过这种不同的方式,我总是遇到某种障碍。如果有必要,我可以用完全不同的方式重写声明。我尝试过使用完全外部联接,使用employee表作为基础并构建它,嵌套的select语句等,但总是会遇到某种问题。
BillableActivities
customer resource WeekNum BillableHours Approval
A. Datum Corporation (sample) Employee C 35 2 0
A. Datum Corporation (sample) Employee A 35 1 0
B. Trippin Corporation (sample) Employee B 35 2 1
B. Trippin Corporation (sample) Employee A 35 16 0
ForecastedActivities
Customer Resource ActivityName EstHours WeekNum
A. Datum Corporation (sample) Employee A Test 4 35
A. Datum Corporation (sample) Employee B Publish 2 35
B. Trippin Corporation (sample) Employee A Build 3 35
B. Trippin Corporation (sample) Employee B Rework 3 35
所需输出
Customer Resource Wk 1 Forecast Wk 1 Planned Wk 1 To Bill
A. Datum Corporation (sample) Employee A 3 0 0
A. Datum Corporation (sample) Employee B 6 0 0
A. Datum Corporation (sample) Employee C 0 2 2
B. Trippin Corporation (sample) Employee A 2 0 2
B. Trippin Corporation (sample) Employee B 7 0 0
B. Trippin Corporation (sample) Employee D 8 0 0
当前查询 - 请注意,这会过滤到当前周
select a.Customer,a.Resource,
sum(a.EstHours) as [Week 1 Forecast],
ISNULL(sum(c.billablehours),0) as [Week 1 Planned],
ISNULL(sum(b.BillableHours),0) as [Week 1 To Bill],
CAST(MAX(CAST(a.Onsite as INT)) as bit) as Onsite1
from ForecastedActivities a
left join BillableActivities b on (a.Customer = b.Customer) and (a.Resource = b.Resource) and (a.WeekNum = b.WeekNum) and b.Approval = 1
left join BillableActivities c on (a.Customer = c.Customer) and (a.Resource = c.Resource) and (a.WeekNum = c.WeekNum) and b.Approval = 0
where a.WeekNum = (DATEPART(week,getdate()))
group by a. Customer, a.Resource
UNION
select a.Customer,a.Resource,
0 as [Week 1 Forecast],
ISNULL(sum(c.billablehours),0) as [Week 1 Planned],
ISNULL(sum(b.BillableHours),0) as [Week 1 To Bill]
,CAST(MAX(CAST(a.BillableHours as INT)) as bit) as Onsite1
from BillableActivities a
left join BillableActivities b on (a.Customer = b.Customer) and (a.Resource = b.Resource) and (a.WeekNum = b.WeekNum) and b.Approval = 1
left join BillableActivities c on (a.Customer = c.Customer) and (a.Resource = c.Resource) and (a.WeekNum = c.WeekNum) and b.Approval = 0
where a.WeekNum = (DATEPART(week,getdate())) and
a.Resource not in (select Resource from ForecastedActivities where WeekNum = (DATEPART(week,getdate())))
group by a.Resource, a. Customer
order by Customer, Resource
非常感谢您提供的任何帮助。
答案 0 :(得分:1)
我不确定您在使用Onsite1列时尝试了什么,所以我将其排除在外。但是,使用完全外部联接并选择非空客户和资源时,其余部分是破解。我使用案例陈述总结了批准/未批准的计费小时数:
select
ISNULL(f.Customer, b.customer) AS Customer,
ISNULL(f.resource, b.resource) AS Resource,
ISNULL(SUM(f.EstHours) + SUM(CASE WHEN b.approval=0 THEN b.billablehours ELSE 0 END),0) AS [Week 1 Forecast],
ISNULL(sum(CASE WHEN b.approval=1 THEN b.billablehours ELSE 0 END),0) as [Week 1 To Bill]
from ForecastedActivities f
full outer join BillableActivities b
on b.customer = f.customer
and b.resource = f.resource
and b.WeekNum = f.WeekNum
where f.WeekNum = DATEPART(week,getdate())
group by ISNULL(f.Customer, b.customer), ISNULL(f.resource, b.resource)
order by ISNULL(f.Customer, b.customer), ISNULL(f.resource, b.resource)
答案 1 :(得分:0)
Customer,Resource,WeekNum
的列表 - 这是CTE_Main
。如果您只对特定的一周感兴趣,请为所有查询添加相应的过滤器。
WITH
CTE_Main
AS
(
SELECT
Customer
,Resource
,WeekNum
FROM BillableActivities
UNION
SELECT
Customer
,Resource
,WeekNum
FROM ForecastedActivities
)
,CTE_ToBill
AS
(
SELECT
Customer
,Resource
,WeekNum
,SUM(BillableHours) AS SumToBill
FROM BillableActivities
WHERE Approval = 1
GROUP BY
Customer
,Resource
,WeekNum
)
,CTE_Planned
AS
(
SELECT
Customer
,Resource
,WeekNum
,SUM(BillableHours) AS SumPlanned
FROM BillableActivities
WHERE Approval = 0
GROUP BY
Customer
,Resource
,WeekNum
)
,CTE_Forecast
AS
(
SELECT
Customer
,Resource
,WeekNum
,SUM(EstHours) AS SumForecast
FROM ForecastedActivities
GROUP BY
Customer
,Resource
,WeekNum
)
SELECT
CTE_Main.Customer
,CTE_Main.Resource
,CTE_Main.WeekNum
,ISNULL(CTE_Forecast.SumForecast, 0) AS SumForecast
,ISNULL(CTE_Planned.SumPlanned, 0) AS SumPlanned
,ISNULL(CTE_ToBill.SumToBill, 0) AS SumToBill
FROM
CTE_Main
LEFT JOIN CTE_Forecast ON
CTE_Forecast.Customer = CTE_Main.Customer AND
CTE_Forecast.Resource = CTE_Main.Resource AND
CTE_Forecast.WeekNum = CTE_Main.WeekNum
LEFT JOIN CTE_Planned ON
CTE_Planned.Customer = CTE_Main.Customer AND
CTE_Planned.Resource = CTE_Main.Resource AND
CTE_Planned.WeekNum = CTE_Main.WeekNum
LEFT JOIN CTE_ToBill ON
CTE_ToBill.Customer = CTE_Main.Customer AND
CTE_ToBill.Resource = CTE_Main.Resource AND
CTE_ToBill.WeekNum = CTE_Main.WeekNum
;