Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Uzyskaj zaktualizowaną wartość poprzedniego wiersza za pomocą LAG Bez użycia rekurencyjnego CTE

Wydajność tutaj cierpi z powodu rekurencji CTE. Samo CTE to tylko cukier składniowy.

Tylko dla tych konkretnych przykładowych danych działa to bez rekurencji:

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;

Może to pomóc w ocenie wydajności, ale zakończy się niepowodzeniem, jeśli w dowolnym bloku Debit s przekracza sumę Credit s. Jeśli BlockTotal jest ujemna, to musi zostać scalona z jednym lub kilkoma kolejnymi blokami i nie można tego zrobić bez iteracji lub rekurencji.

W prawdziwym życiu zrzuciłbym CTE3 do tabeli tymczasowej i cyklicznie, łącząc bloki, aż nie będzie więcej negatywnych BlockTotal s.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Pobierz dzień tygodnia w SQL Server 2005/2008

  2. Sql Server 2008 NVARCHAR długość -1

  3. Jak zaktualizować wartość atrybutu xml w zmiennej xml za pomocą t-sql?

  4. Jakiego typu danych należy używać do przechowywania wartości pieniężnych?

  5. Dynamicznie decyduj o nazwie tabeli w wykonaniu zadania SQL dla instrukcji CREATE TABLE