简体   繁体   English

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

[英]Add first row decimal value to next rows in SQL Server

I have table, as below and its contains customer electricity volume for the period as.我有下表,如下所示,其中包含该期间的客户电量。 Available data like可用数据如

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 

For this OwnerID = 1 , having existing some volume 0.90.对于此OwnerID = 1 ,存在一些卷 0.90。 This should apply first row (add)这应该适用于第一行(添加)

  1. Get the whole number and decimal part value获取整数和小数部分值
  2. the first row returned decimal value should add to next row and vice vera.第一行返回的十进制值应该添加到下一行,反之亦然。

ExistingVolume - 0.90现有体积 - 0.90

So expected result set should like:所以预期的结果集应该是:

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 

Could you someone suggest how to achieve this is in SQL query?有人能建议如何在 SQL 查询中实现这一点吗?

The example below uses a cumulative sum and a few CTE's to calculate those 2 columns.下面的示例使用累积总和和一些 CTE 来计算这 2 列。

Sample data:样本数据:

 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) ;

Query:询问:

 ;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
\nOwnerId |所有者 ID | StartDate |开始日期 | EndDate |结束日期 | CalculatedVolume |计算体积 | AppliedExistingVolume |应用现有体积 | RemainExistingVolume保持现有量\n------: | ------: | :------------------ | :------------------ | :------------------ | :------------------ | :--------------- | :--------------- | :-------------------- | :-------------------- | :------------------- :--------------------\n      1 | 1 | 01/01/2019 00:00:00 | 01/01/2019 00:00:00 | 15/01/2019 00:00:00 | 15/01/2019 00:00:00 | 11 | 11 | 0.60 | 0.60 | 0.30 0.30                \n      1 | 1 | 16/01/2019 00:00:00 | 16/01/2019 00:00:00 | 31/01/2019 00:00:00 | 31/01/2019 00:00:00 | 6 | 6 | 0.20 | 0.20 | 0.10 0.10                \n      1 | 1 | 01/02/2019 00:00:00 | 01/02/2019 00:00:00 | 10/02/2019 00:00:00 | 10/02/2019 00:00:00 | 8 | 8 | 0.10 | 0.10 | 0.00 0.00                \n      1 | 1 | 11/02/2019 00:00:00 | 11/02/2019 00:00:00 | 28/02/2019 00:00:00 | 28/02/2019 00:00:00 | 9 | 9 | 0.00 | 0.00 | 0.50 0.50                \n

db<>fiddle here db<> 在这里摆弄

When requirement is absolutely clear then you can think of better solution ie Set Based Approach当需求绝对明确时,您可以想到更好的解决方案,即Set Based Approach

When requirement is not so clear then you think of solution like RBAR .当需求不是那么清楚时,你会想到像RBAR这样的解决方案。

Suppose I was to calculate the output in Excel then what formula I will apply ?假设我要在 Excel 中计算输出,那么我将应用什么公式?

There have to have some formula but requirement is not clear.必须有一些公式,但要求不明确。

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