过滤UNION中的第二个语句以防止重复结果

时间:2015-08-04 22:51:54

标签: sql-server select union

我四处走动,无法弄清楚如何解决这个问题。我有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

非常感谢您提供的任何帮助。

2 个答案:

答案 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
  • 然后将您的小时总和三次:批准,未批准,预测。
  • 然后将加入总和留给主CTE。

SQL Fiddle

如果您只对特定的一周感兴趣,请为所有查询添加相应的过滤器。

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
;