[英]Add first row decimal value to next rows in SQL Server
我有下表,如下所示,其中包含该期间的客户电量。 可用数据如
OwnerID StartDate EndDate Volume
---------------------------------------
1 2019-01-01 2019-01-15 10.40
1 2019-01-16 2019-01-31 5.80
1 2019-02-01 2019-02-10 7.90
1 2019-02-11 2019-02-28 8.50
对于此OwnerID = 1
,存在一些卷 0.90。 这应该适用于第一行(添加)
现有体积 - 0.90
所以预期的结果集应该是:
OwnerId StartDate EndDate CalulatedVolume AppliedExistingVolume(0.90) RemainExistingVolume
----------------------------------------------------------------------------------------------------
1 2019-01-01 2019-01-15 11 0.60 0.30
1 2019-01-16 2019-01-31 6 0.20 0.10
1 2019-02-01 2019-02-10 8 0.10 0.00
1 2019-02-11 2019-02-28 8 0.00 0.50
有人能建议如何在 SQL 查询中实现这一点吗?
下面的示例使用累积总和和一些 CTE 来计算这 2 列。
样本数据:
create table yourtable ( Id int identity(1,1) primary key, OwnerID int not null, StartDate date not null, EndDate date not null, Volume decimal(16,2) not null ); insert into yourtable (OwnerID, StartDate, EndDate, Volume) values (1, '2019-01-01', '2019-01-15', 10.40) , (1, '2019-01-16', '2019-01-31', 5.80) , (1, '2019-02-01', '2019-02-10', 7.90) , (1, '2019-02-11', '2019-02-28', 8.50) ;
询问:
;with CTE_EXISTING_VOLUMES AS ( select * from (values (1, 0.9) ) q(OwnerId, ExistingVolume) ) , CTE_DATA AS ( select t.*, c.ExistingVolume , ceiling(t.Volume) - t.Volume as VolumeRemainder , sum(ceiling(t.Volume) - t.Volume) over (partition by t.OwnerID order by t.StartDate) as CumSumVolumeRemainder from yourtable t left join CTE_EXISTING_VOLUMES c on t.OwnerID = c.OwnerID ) , CTE_DATA2 AS ( select * , ceiling(Volume) as CalculatedVolume , IIF(ExistingVolume < CumSumVolumeRemainder, 0.0, (ceiling(Volume) - Volume)) as AppliedExistingVolume from CTE_DATA ) select OwnerId, StartDate, EndDate , CalculatedVolume , AppliedExistingVolume , case when AppliedExistingVolume > 0 then ExistingVolume - CumSumVolumeRemainder else VolumeRemainder end as RemainExistingVolume from CTE_DATA2; GO
\n所有者 ID | 开始日期 | 结束日期 | 计算体积 | 应用现有体积 | 保持现有量\n ------: | :------------------ | :------------------ | :--------------- | :-------------------- | :--------------------\n 1 | 01/01/2019 00:00:00 | 15/01/2019 00:00:00 | 11 | 0.60 | 0.30 \n 1 | 16/01/2019 00:00:00 | 31/01/2019 00:00:00 | 6 | 0.20 | 0.10 \n 1 | 01/02/2019 00:00:00 | 10/02/2019 00:00:00 | 8 | 0.10 | 0.00 \n 1 | 11/02/2019 00:00:00 | 28/02/2019 00:00:00 | 9 | 0.00 | 0.50 \n
db<> 在这里摆弄
当需求绝对明确时,您可以想到更好的解决方案,即Set Based Approach
当需求不是那么清楚时,你会想到像RBAR
这样的解决方案。
假设我要在 Excel 中计算输出,那么我将应用什么公式?
必须有一些公式,但要求不明确。
create table #temp(OwnerID int, StartDate date,EndDate date,Volume decimal(5,2))
insert into #temp values
(1,'2019-01-01','2019-01-15', 10.40)
,(1,'2019-01-16','2019-01-31', 5.80)
,(1,'2019-02-01','2019-02-10', 7.90)
,(1,'2019-02-11','2019-02-28', 8.50)
declare @ExistingVolume decimal(5,2)=0.90
;with CTE as
(
select *
,ROW_NUMBER()over(partition by ownerid order by startdate)rn
from #temp
),
CTE1 as
(
select ownerid
,startdate,enddate,Volume
,Cast((c.Volume+@ExistingVolume) as int) CalulatedVolume
,Cast((c.Volume+@ExistingVolume) as int)-c.Volume as AppliedExistingVolume
,cast((c.Volume+@ExistingVolume-
cast((c.Volume+@ExistingVolume) as int) )as decimal(5,2)) as RemainExistingVolume
,rn
from CTE C where rn=1
union all
select c.ownerid
,c.startdate,c.enddate,c.Volume
,cast((c.Volume+c1.RemainExistingVolume) as int) as CalulatedVolume
,cast((c.Volume+c1.RemainExistingVolume) as int)-c.Volume as AppliedExistingVolume
,cast(((c.Volume+c1.RemainExistingVolume)
-cast((c.Volume+c1.RemainExistingVolume) as int)) as decimal(5,2))
,c.rn
from CTE C
inner join CTE1 C1 on c.OwnerID=c1.OwnerID
where c.rn=c1.rn+1
)
select ownerid,
startdate,enddate
,CalulatedVolume
,case when AppliedExistingVolume<0 then 0
else AppliedExistingVolume end as AppliedExistingVolume
,RemainExistingVolume
from CTE1
drop table #temp
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.