将当月销售额与上月销售额进行比较
Compare current month sales with previous month sales
获取测试数据的代码:
create table SalesCalls
(
EmpId INT NOT NULL,
EmpName nvarchar(20),
month INT,
Year INT,
CallsMade INT
)
GO
Insert into SalesCalls values
(1,'ABC',12,2018,10),
(1,'ABC',1,2019,15),
(1,'ABC',2,2019,20),
(2,'DEF',12,2018,12),
(2,'DEF',1,2019,14),
(2,'DEF',2,2019,26)
GO
objective是比较某员工当月销售额与该员工上月销售额的百分比变化。使用以下查询实现:
With SalesCTE as
(
select EmpId,EmpName,
Month As CurrentMonth,
Year as CurrentMonthYear,
Case When month = 1 then 12 Else (Month-1) End AS PrevMonth,
Case when month = 1 then (Year - 1) Else Year End As PrevMonthYear,
CallsMade
from SalesCalls
)
select
S1.EmpId, S1.EmpName, S1.CurrentMonth, S1.CurrentMonthYear, S1.CallsMade as CurrentMonthCalls,
S2.CurrentMonth as PrevMont,
S2.CurrentMonthYear as PrevMonthYear,
S2.CallsMade as PrevMonthCalls,
( CONVERT(numeric(5,2),S1.CallsMade) / S2.CallsMade) * 100 As PercentageChange
from SalesCTE S1
JOIN SalesCTE S2 ON S1.EmpId = S2.EmpId
AND S1.PrevMonth = S2.CurrentMonth
AND S1.PrevMonthYear = S2.CurrentMonthYear
ORDER BY S1.EmpId, S1.CurrentMonth, S1.CurrentMonthYear
以上查询一直有效,直到同一个月的员工没有冗余记录。
但后来来自多个来源的数据进来了,一个员工 table 可以在同一个月有多个记录并且它仍然有效。因为员工可能会以不同的方式拨打电话。例如,下面的记录被插入到 table:
Insert into SalesCalls values
(1,'ABC',1,2019,1)
上面的查询在比较当前月份的 SalesCalls 与上个月时运行良好,但现在不再有效。
用例的第 2 阶段:
因此,为了解决这个问题,我构建了一个包含聚合数据的中间温度 table。使用的查询是:
Select EmpId, EmpName, month, Year, SUM(CallsMade) as CallsMade
into #SalesCalls
from SalesCalls
group by EmpId, EmpName, month, Year
现在 CTE 中的 SalesCalls
table 被替换为 #SalesCalls
然后上面的查询工作正常。
但是这个#SalesCalls
table每次都需要drop重新创建才能看到最新的对比数据
问题是,是否可以仅使用单个查询而不使用中间临时 tables 或视图来获取比较数据。
只需使用window函数:
select EmpId, EmpName, month, Year,
sum(CallsMade) as CallsMade,
(case when lag(year * 12 + month) over (partition by empId order by year, month) = year * 12 + month - 1
then lag(sum(callsMade)) over (partition by empId order by year, month)
end) as prevMonthCalls,
(case when lag(year * 12 + month) over (partition by empId order by year, month) = year * 12 + month - 1
then callsMade * 100.0 / lag(sum(callsMade) over (partition by empId order by year, month)
end) as as perentageChange
from SalesCalls
group by EmpId, EmpName, month, Year;
根本不需要 join
s、CTE、子查询或临时表。
最简单的解决方案之一:
select EmpId, EmpName, month, Year,
sum(CallsMade) as CallsMade,
lag(sum(callsMade)) over (partition by empId order by year, month) AS prevMonthCalls,
sum(CallsMade) * 100.0 / lag(sum(CallsMade)) over (partition by empId order by year, month) as PercentageChange
from SalesCalls
group by EmpId, EmpName, month, Year
order by EmpId, Year,month;
获取测试数据的代码:
create table SalesCalls
(
EmpId INT NOT NULL,
EmpName nvarchar(20),
month INT,
Year INT,
CallsMade INT
)
GO
Insert into SalesCalls values
(1,'ABC',12,2018,10),
(1,'ABC',1,2019,15),
(1,'ABC',2,2019,20),
(2,'DEF',12,2018,12),
(2,'DEF',1,2019,14),
(2,'DEF',2,2019,26)
GO
objective是比较某员工当月销售额与该员工上月销售额的百分比变化。使用以下查询实现:
With SalesCTE as
(
select EmpId,EmpName,
Month As CurrentMonth,
Year as CurrentMonthYear,
Case When month = 1 then 12 Else (Month-1) End AS PrevMonth,
Case when month = 1 then (Year - 1) Else Year End As PrevMonthYear,
CallsMade
from SalesCalls
)
select
S1.EmpId, S1.EmpName, S1.CurrentMonth, S1.CurrentMonthYear, S1.CallsMade as CurrentMonthCalls,
S2.CurrentMonth as PrevMont,
S2.CurrentMonthYear as PrevMonthYear,
S2.CallsMade as PrevMonthCalls,
( CONVERT(numeric(5,2),S1.CallsMade) / S2.CallsMade) * 100 As PercentageChange
from SalesCTE S1
JOIN SalesCTE S2 ON S1.EmpId = S2.EmpId
AND S1.PrevMonth = S2.CurrentMonth
AND S1.PrevMonthYear = S2.CurrentMonthYear
ORDER BY S1.EmpId, S1.CurrentMonth, S1.CurrentMonthYear
以上查询一直有效,直到同一个月的员工没有冗余记录。
但后来来自多个来源的数据进来了,一个员工 table 可以在同一个月有多个记录并且它仍然有效。因为员工可能会以不同的方式拨打电话。例如,下面的记录被插入到 table:
Insert into SalesCalls values
(1,'ABC',1,2019,1)
上面的查询在比较当前月份的 SalesCalls 与上个月时运行良好,但现在不再有效。
用例的第 2 阶段: 因此,为了解决这个问题,我构建了一个包含聚合数据的中间温度 table。使用的查询是:
Select EmpId, EmpName, month, Year, SUM(CallsMade) as CallsMade
into #SalesCalls
from SalesCalls
group by EmpId, EmpName, month, Year
现在 CTE 中的 SalesCalls
table 被替换为 #SalesCalls
然后上面的查询工作正常。
但是这个#SalesCalls
table每次都需要drop重新创建才能看到最新的对比数据
问题是,是否可以仅使用单个查询而不使用中间临时 tables 或视图来获取比较数据。
只需使用window函数:
select EmpId, EmpName, month, Year,
sum(CallsMade) as CallsMade,
(case when lag(year * 12 + month) over (partition by empId order by year, month) = year * 12 + month - 1
then lag(sum(callsMade)) over (partition by empId order by year, month)
end) as prevMonthCalls,
(case when lag(year * 12 + month) over (partition by empId order by year, month) = year * 12 + month - 1
then callsMade * 100.0 / lag(sum(callsMade) over (partition by empId order by year, month)
end) as as perentageChange
from SalesCalls
group by EmpId, EmpName, month, Year;
根本不需要 join
s、CTE、子查询或临时表。
最简单的解决方案之一:
select EmpId, EmpName, month, Year,
sum(CallsMade) as CallsMade,
lag(sum(callsMade)) over (partition by empId order by year, month) AS prevMonthCalls,
sum(CallsMade) * 100.0 / lag(sum(CallsMade)) over (partition by empId order by year, month) as PercentageChange
from SalesCalls
group by EmpId, EmpName, month, Year
order by EmpId, Year,month;