每个总和都带有 WHERE 子句的 SUM 函数?
Posted
技术标签:
【中文标题】每个总和都带有 WHERE 子句的 SUM 函数?【英文标题】:SUM Function with WHERE clause for each sum? 【发布时间】:2020-10-30 18:02:38 【问题描述】:我有两张桌子:Staff和Hours。
员工(200 多行)与:
员工 ID、姓名、职位
每个员工在此表中只出现一次
小时数(1000 多行):
Staff_ID、小时、金额、BillableFlag、Office、DatePeriod
每个工作人员在此表中出现多次
我需要一个查询,该查询从 Staff 表中提取所有 Staff,其中 position = 'Assistant' 并且 Hours 表中的 Hours 和 Amount 列分别求和两次,每次求和的逻辑不同。
类似这样(这是一个带有一些简单英语的查询以帮助解释):
select s.name,
sum(h.hours) as 'Hours_Not_Billable' --[NEED IT TO SUM ONLY HOURS WHERE h.BILLABLEFLAG <> 'Y', h.office = '2', h.period = 'Q3' AND ONLY DO IT FOR EACH STAFF MEMBER],
sum(h.amount) as 'Amount_Not_Billable' --[NEED IT TO SUM ONLY AMOUNT WHERE h.BILLABLEFLAG <> 'Y', h.office = '2', h.period = 'Q3' AND ONLY DO IT FOR EACH STAFF MEMBER],
sum(h.hours) as 'Hours_Billable' --[NEED IT TO SUM ONLY HOURS WHERE h.BILLABLEFLAG = 'Y', h.office = '2', h.period = 'Q3' AND ONLY DO IT FOR EACH STAFF MEMBER],
sum(h.amount) as 'Amount_Billable --[NEED IT TO SUM ONLY HOURS WHERE h.BILLABLEFLAG = 'Y', h.office = '2', h.period = 'Q3' AND ONLY DO IT FOR EACH STAFF MEMBER]'
from Staff S
left join Hours H on S.Staff_ID = H.Staff_ID
where s.position = 'Assistant'
group by s.name
非常感谢您的帮助!
谢谢
【问题讨论】:
尝试搜索[tsql] conditional aggregation
。通过在每个 sum
中添加 case
表达式,您可以控制添加哪些值。
【参考方案1】:
使用条件聚合。这个想法是在sum()
中放置一个case
表达式,过滤掉的值会被考虑在内。
您的伪代码将翻译为:
select
s.name,
sum(case when h.billableflag <> 'Y' then h.hours else 0 end) hours_not_billable,
sum(case when h.billableflag <> 'Y' then h.amount else 0 end) amount_not_billable,
sum(case when h.billableflag = 'Y' then h.hours else 0 end) hours_billable,
sum(case when h.billableflag = 'Y' then h.amount else 0 end) amount_billable
from staff s
left join hours h
on s.staff_id = h.staff_id and h.office = 2 and h.period = 'Q3'
where s.position = 'Assistant'
group by s.name
注意:大部分条件对所有表达式都是通用的,所以我将它们移到了left join
的on
子句中。
【讨论】:
我认为最好将其他条件 (h.office = 2 and h.period = 'Q3'
) 移动到 WHERE
子句并使用索引列保留连接以获得更好的性能。你同意吗?
@SaeedEsmaeelinejad:这不会做同样的事情。我们有一个left join
:将条件放在where
子句中会将其转换为inner join
。【参考方案2】:
您可以在 SUM() 聚合函数中使用 CASE WHEN,如下所示
select
s.name,
sum(case when h.BILLABLEFLAG <> 'Y' and h.office = '2' and h.DatePeriod = 'Q3' then h.hours else null end) as 'Hours_Not_Billable',
sum(case when h.BILLABLEFLAG <> 'Y' and h.office = '2' and h.DatePeriod = 'Q3' then h.amount else null end) as 'Amount_Not_Billable',
sum(case when h.BILLABLEFLAG = 'Y' and h.office = '2' and h.DatePeriod = 'Q3' then h.hours else null end) as 'Hours_Billable',
sum(case when h.BILLABLEFLAG = 'Y' and h.office = '2' and h.DatePeriod = 'Q3' then h.amount else null end ) as 'Amount_Billable'
from Staff S
left join Hours H on S.Staff_ID = H.Staff_ID
where s.position = 'Assistant'
group by s.name
【讨论】:
以上是关于每个总和都带有 WHERE 子句的 SUM 函数?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用具有相同值的 OVER 子句的 SUM 函数按列返回正确的总和?