繁体   English   中英

将第一行十进制值添加到 SQL Server 中的下一行

[英]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。 这应该适用于第一行(添加)

  1. 获取整数和小数部分值
  2. 第一行返回的十进制值应该添加到下一行,反之亦然。

现有体积 - 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM