Sql server 筛选UNION中的第二条语句以防止重复结果

Sql server 筛选UNION中的第二条语句以防止重复结果,sql-server,select,union,Sql Server,Select,Union,我走来走去,不太明白如何解决这个问题。我有两张桌子。其中一条记录中,每个员工/客户/周最多包含1条记录,列出他们在该周的估计工作小时数。这是下表中列出的“预测活动”。另一个表列出了计费活动。一个给定的员工可能在一周内为一个给定的客户拥有多个计费活动记录。表“可计费活动”中列出了这些活动 我正试图创建一个select语句,该语句将返回所有这些信息的摘要,如下面的“所需输出”表所示,但需要一些额外的聚合和筛选。输出应将预测小时数作为所有计费小时数的总和(其中批准=1)作为“计费小时数”,将所有计费小

我走来走去,不太明白如何解决这个问题。我有两张桌子。其中一条记录中,每个员工/客户/周最多包含1条记录,列出他们在该周的估计工作小时数。这是下表中列出的“预测活动”。另一个表列出了计费活动。一个给定的员工可能在一周内为一个给定的客户拥有多个计费活动记录。表“可计费活动”中列出了这些活动

我正试图创建一个select语句,该语句将返回所有这些信息的摘要,如下面的“所需输出”表所示,但需要一些额外的聚合和筛选。输出应将预测小时数作为所有计费小时数的总和(其中批准=1)作为“计费小时数”,将所有计费小时数的总和(其中批准=0)作为“计划小时数”

我怀疑有比我所做的更直接的方法,但我已经非常接近了。我一直关注的问题是,有时在给定的一周内,员工会有预测的小时数,但没有计费小时数,反之亦然。为了帮助实现这一点,我创建了一个联盟,但我知道这个联盟不会按预期工作,因为如果该资源存在于该周的预测活动中,即使对于其他客户,它也将被排除在第二个声明之外。我尝试过几种不同的方法,但总是遇到一些障碍。如果必要的话,我可以用完全不同的方式重写这个声明。我尝试过使用完整的外部联接,使用employee表作为基础,并在此基础上构建嵌套的select语句,等等,但总是遇到一些问题

收费活动

预测活动

期望输出

当前查询-请注意,此查询将筛选到当前周

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

如果您能提供任何帮助,我们将不胜感激。

我不确定您对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)
  • 首先,获取所有
    客户、资源、周数的列表
    ——这是
    CTE\u Main
  • 然后将你的工作时间加三次:批准、未批准、预测
  • 然后将连接和左移到主CTE

如果您只对某一周感兴趣,请为所有查询添加相应的筛选器

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
;

如果您可以为此设置sql fiddle,那就太好了。sql fiddle在您所需的输出中可用,您有
员工D
,但它不在
计费活动中,也不在
预测活动中。它来自哪里?在SQL FIDLE中,您有一组不同的示例数据。如果你在提琴中包含一个表格,根据提琴中包含的样本数据得出想要的结果,这会有所帮助。你现在可以忽略现场数据。查询似乎没有像我在查询中所做的那样,向下过滤到某个特定的星期。我在介绍中没有提到这一点。整个事件应该被过滤到当前周数(32)。另外,不确定您是否看到了,但这可以在sql fiddle@@LearningCurve中找到。我在介绍中没有提到这一点。然后编辑问题,而不是通过注释添加需求查询似乎没有向下过滤到特定的一周,然后只需为该周添加一个过滤器。morgb的查询与问题中给出的预期结果匹配请参见:@LearningCurve Ok-我编辑了查询以包含周数的筛选器(基于原始查询中演示的方法)。
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
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)
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
;