在SQL中计算平均每日余额

时间:2016-05-23 20:23:25

标签: sql sql-server

从表开始;

[AccountLedger]

AccountCode PostingDate            Amount    
128         2014-01-01 08:36:09    200.00
128         2014-01-01 14:18:10    200.00
128         2014-01-01 14:26:56      0.00
128         2014-01-01 18:17:31    400.00
128         2014-01-01 20:18:53    100.00
128         2014-01-02 00:10:35      0.00
128         2014-01-02 01:44:26    300.00
128         2014-01-02 15:49:31   -300.00
128         2014-01-03 00:33:23    400.00
128         2014-01-03 11:55:13   -200.00
128         2014-01-03 11:56:34   -100.00
128         2014-01-03 14:58:42   -400.00    
128         2014-01-03 17:31:11      0.00

**REQUIRED RESULT**

AccountCode PostingDate         daily_balance 
128         2014-01-01          900.00
128         2014-01-02          900.00
128         2014-01-03          600.00

追加查询

select 
      Acc
    , Dte 
    , sum(daily_amt) over (PARTITION BY Acc ORDER BY Dte DESC) as daily_balance 
from (select 
            [AccountLedger].[AccountCode] as Acc
          , convert(date, [AccountLedger].[PostingDate])   as Dte
          , sum([AccountLedger].[Amount]) as daily_amt
      from [AccountLedger]
      WHERE [AccountLedger].[PostingDate] < '2014-04-01'
      and [AccountLedger].[AccountCode]=128

      group by  [AccountLedger].AccountCode
      , [AccountLedger].[PostingDate]

      ) t
       order by Acc, dte*

*但出现错误;

Msg 102, Level 15, State 1, Line 4
Incorrect syntax near 'order'.
Msg 102, Level 15, State 1, Line 16
Incorrect syntax near 't'.*

如何获得所需的结果?

3 个答案:

答案 0 :(得分:1)

使用简单的日期表(或者在我的情况下使用udf来生成日期范围)

Declare @DateR1 Date,@DateR2 Date
Set @DateR1 = '2014-01-01'
Set @DateR2 = '2014-01-31'


Select AccountCode
      ,PostingDate=Date2
      ,DailyBalance=sum(amount) 
 From  #Temp A
 Join (Select Date1=@DateR1,Date2=cast(RetVal as Date) from [dbo].[udf-Create-Range-Date](@DateR1,@DateR2,'DD',1)) B on cast(PostingDate as Date) between Date1 and Date2
 Group By AccountCode,Date2 
 Order By 1

返回

AccountCode PostingDate DailyBalance
128         2014-01-01  900
128         2014-01-02  900
128         2014-01-03  600
128         2014-01-04  600
128         2014-01-05  600
128         2014-01-06  600
...
128         2014-01-31  600

UDF

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [dbo].[udf-Create-Range-Date] (@DateFrom datetime,@DateTo datetime,@DatePart varchar(10),@Incr int)

Returns 
@ReturnVal Table (RetVal datetime)

As
Begin
    With DateTable As (
        Select DateFrom = @DateFrom
        Union All
        Select Case @DatePart
               When 'YY' then DateAdd(YY, @Incr, df.dateFrom)
               When 'QQ' then DateAdd(QQ, @Incr, df.dateFrom)
               When 'MM' then DateAdd(MM, @Incr, df.dateFrom)
               When 'WK' then DateAdd(WK, @Incr, df.dateFrom)
               When 'DD' then DateAdd(DD, @Incr, df.dateFrom)
               When 'HH' then DateAdd(HH, @Incr, df.dateFrom)
               When 'MI' then DateAdd(MI, @Incr, df.dateFrom)
               When 'SS' then DateAdd(SS, @Incr, df.dateFrom)
               End
        From DateTable DF
        Where DF.DateFrom < @DateTo
    )

    Insert into @ReturnVal(RetVal) Select DateFrom From DateTable option (maxrecursion 32767)

    Return
End

-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2020-10-01','YY',1) 
-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2020-10-01','DD',1) 
-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2016-10-31','MI',15) 
-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2016-10-02','SS',1) 

答案 1 :(得分:0)

您的查询运行正常。但它没有按照您的意图行事,因为您按日期时间字段进行分组,而2014-01-01 00:00:00与2014-01-01 00:00:01不同。

这是基于日期汇总金额的非常简单的方法

SELECT [AccountCode] ,cast([PostingDate] as date) as date ,sum([Amount]) as 'daily balance' FROM [AccountLedger] WHERE [PostingDate] < '2014-04-01' GROUP BY [AccountCode], cast([PostingDate] as date)

让我知道这是否有效。

答案 2 :(得分:0)

select 
    AccountCode,
    convert(date, PostingDate) AS PostingDate,
    avg(Amount) as Average
from
  AccountLedger
where
  PostingDate < '2014-04-01'
group by
  AccountCode,
  convert(date, PostingDate)

http://sqlfiddle.com/#!6/965ec/19