Sql server 2012 N也许可以尝试手动运行电子表格中的示例数据以获得参考结果?CTE本身不承担任何性能处罚。如果你真的只需要“previous value”中的“previous value”,那么你所需要的就是LAG(…,2)。因此,对于PreviousDebit您可以重写

Sql server 2012 N也许可以尝试手动运行电子表格中的示例数据以获得参考结果?CTE本身不承担任何性能处罚。如果你真的只需要“previous value”中的“previous value”,那么你所需要的就是LAG(…,2)。因此,对于PreviousDebit您可以重写,sql-server-2012,lag,Sql Server 2012,Lag,N也许可以尝试手动运行电子表格中的示例数据以获得参考结果?CTE本身不承担任何性能处罚。如果你真的只需要“previous value”中的“previous value”,那么你所需要的就是LAG(…,2)。因此,对于PreviousDebit您可以重写TotalDebit表达式,增加计算中使用的每个值的LAG。@Y.B.,我没有使用电子表格进行检查,但我使用CTE使用sql进行了检查。它正在工作,但速度非常慢……ISNULL(滞后(T.Debit)超过(按SNO排序),0)实际上应该是LAG


N也许可以尝试手动运行电子表格中的示例数据以获得参考结果?CTE本身不承担任何性能处罚。如果你真的只需要“previous value”中的“previous value”,那么你所需要的就是
LAG(…,2)
。因此,对于
PreviousDebit
您可以重写
TotalDebit
表达式,增加计算中使用的每个值的
LAG
。@Y.B.,我没有使用电子表格进行检查,但我使用CTE使用sql进行了检查。它正在工作,但速度非常慢……
ISNULL(滞后(T.Debit)超过(按SNO排序),0)
实际上应该是
LAG(T.Debit,1,0)超过(按SNO排序)
TotalDebit
不应该是一个运行总数吗?目前,列名具有误导性,因为实际值是两个借项的总和,可以选择减少一个贷项。
 Declare @Tbl as Table(SNO Int,Credit Money,Debit Money,PaidDate Date)
Insert into @Tbl
SELECT * FROM (VALUES (1,0,12,'7Jan16'), (2,10,0,'6Jan16'), (3,15,0,'5Jan16'), (4,0,5,'4Jan16'), (5,0,3,'3Jan16'), (6,0,2,'2Jan16'), (7,20,0,'1Jan16')) AS X(SNO,Credit,Debit,PaidDate)

Select
    T.SNO,
    T.Credit,
    T.Debit,
    TotalDebit = Case When Credit < LAG(T.Debit, 1, 0) OVER (ORDER BY SNO) Then Debit + (LAG(T.Debit, 1, 0) OVER (ORDER BY SNO)-Credit) Else Debit End,
    Amount = Case When Credit < LAG(T.Debit, 1, 0) OVER (ORDER BY SNO) Then 0 Else Credit-LAG(T.Debit, 1, 0) OVER (ORDER BY SNO) End,
    T.PaidDate
From @Tbl T
Declare @Tbl as Table(SNO Int,Credit Money,Debit Money,PaidDate Date)
Insert into @Tbl
SELECT * FROM (VALUES (1,0,12,'7Jan16'), (2,10,0,'6Jan16'), (3,15,0,'5Jan16'), (4,0,5,'4Jan16'), (5,0,3,'3Jan16'), (6,0,2,'2Jan16'), (7,20,0,'1Jan16')) AS X(SNO,Credit,Debit,PaidDate)


;With Temp As(/* Detect Debited amount */
    Select Top 1 SNO,Credit,Debit,Debit As TotalDebit,Credit As Amount,PaidDate From @Tbl
    Union All
    Select
        R.SNO,
        R.Credit,
        R.Debit,
        TotalDebit = Case When R.Credit < RP.TotalDebit Then R.Debit + (RP.TotalDebit-R.Credit) Else R.Debit End,
        Amount = Case When R.Credit < RP.TotalDebit Then 0 Else R.Credit-RP.TotalDebit End,
        R.PaidDate
    From @Tbl R
    Inner Join Temp RP ON R.SNO-1=RP.SNO
)

Select * From Temp
Declare @Tbl as Table(SNO Int,Credit Money,Debit Money,PaidDate Date)
Insert into @Tbl
SELECT * FROM (VALUES (1,0,12,'7Jan16'), (2,10,0,'6Jan16'), (3,15,0,'5Jan16'), (4,0,5,'4Jan16'), (5,0,3,'3Jan16'), (6,0,2,'2Jan16'), (7,20,0,'1Jan16')) AS X(SNO,Credit,Debit,PaidDate);

With CTE1 As (
    Select *
      , CASE WHEN Credit > 0 THEN LEAD(1 - SIGN(Credit), 1, 1) OVER (ORDER BY SNO) ELSE 0 END As LastCrPerBlock
    From @Tbl
), CTE2 As (
    Select *
      , SUM(LastCrPerBlock) OVER (ORDER BY SNO DESC ROWS UNBOUNDED PRECEDING) As BlockNumber
    From CTE1
), CTE3 As (
    Select *
      , SUM(Credit - Debit) OVER (PARTITION BY BlockNumber) As BlockTotal
      , SUM(Credit - Debit) OVER (PARTITION BY BlockNumber ORDER BY SNO ROWS UNBOUNDED PRECEDING) As BlockRunningTotal
    From CTE2
)
Select SNO, Credit, Debit
  , CASE WHEN BlockRunningTotal < 0 THEN -BlockRunningTotal ELSE 0 END As TotalDebit
  , CASE WHEN BlockRunningTotal > 0 THEN CASE WHEN Credit < BlockRunningTotal THEN Credit ELSE BlockRunningTotal END ELSE 0 END As Amount
  , PaidDate
From CTE3
Order By SNO;
Declare @Tbl as Table(ReceiptNo varchar(50),Credit Money,Debit Money,PaidDate Date)
Insert into @Tbl
SELECT * FROM (VALUES ('R1',20,0,'1Jan16'),('R2',0,2,'2Jan16'),('R3',0,3,'3Jan16'),('R4',0,5,'4Jan16'),('R5',10,0,'5Jan16'),('R6',0,1,'6Jan16'),('R7',0,10,'7Jan16')) AS X(ReceiptNo,Credit,Debit,PaidDate);

With Receipts As (
    Select 
        SNO = ROW_NUMBER() OVER(ORDER BY PaidDate Desc),ReceiptNo,Credit,Debit,PaidDate,
        LastCrPerBlock = CASE WHEN Credit > 0 THEN LEAD(1 - SIGN(Credit), 1, 1) OVER (ORDER BY PaidDate DESC) ELSE 0 END
    From @Tbl
), Blocks As (
    Select *
      , SUM(LastCrPerBlock) OVER (ORDER BY SNO DESC ROWS UNBOUNDED PRECEDING) As BlockNumber
    From Receipts
), BlockTotal As (
    Select *
      , SUM(Credit - Debit) OVER (PARTITION BY BlockNumber) As BlockTotal
      , SUM(Credit - Debit) OVER (PARTITION BY BlockNumber ORDER BY SNO ROWS UNBOUNDED PRECEDING) As BlockRunningTotal
    From Blocks
),
ReceiptAmount As (
    Select ReceiptNo,
        Amount = CASE WHEN BlockRunningTotal > 0 THEN CASE WHEN Credit < BlockRunningTotal THEN Credit ELSE BlockRunningTotal END ELSE 0 END,
        Debit = IIF(BlockNumber<>LEAD(BlockNumber) OVER(ORDER BY SNO) and BlockRunningTotal<0,ABS(BlockRunningTotal),0),
        PaidDate
    From BlockTotal
),
FinalReceipt2012 As (
    Select 
        SNO = ROW_NUMBER() OVER(ORDER BY PaidDate Desc),ReceiptNo,Amount,Debit,PaidDate,
        Recur = IIF(Exists(Select Top 1 R1.Amount From ReceiptAmount R1 Where Debit>0),1,0)
    From ReceiptAmount
    Where Amount>0 or Debit>0
),
FinalReceipt As (
    Select * From FinalReceipt2012 Where Recur=0 OR SNO=1
    Union All
    Select
        R.SNO,R.ReceiptNo,
        Amount = Case When R.Amount < RP.Debit Then 0 Else R.Amount-RP.Debit End,
        Debit = Case When R.Amount < RP.Debit Then R.Debit + (RP.Debit-R.Amount) Else R.Debit End,
        R.PaidDate,0 As Recur
    From FinalReceipt2012 R 
    Inner Join FinalReceipt RP ON R.SNO=RP.SNO+1
    Where R.Recur=1
)

Select ReceiptNo,Amount,PaidDate From FinalReceipt Where Amount>0