Solved

UPDATE Row using values from prior row

Posted on 2008-09-30
9
742 Views
Last Modified: 2012-05-05
Hello,
I have this:

UPDATE MONEY SET Balance = Credit - Debit + "X"

Ok, that "X" is supposed to be the prior row. I need to calculate the Balance, which is the result of the previous balance + the result of credit + debit. The thing is by the nature of our business we need to alter some old rows and recalculate the balance. The update works that way? How to get the value for a column in the previous row?

thanks.
0
Comment
Question by:starusa
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
9 Comments
 
LVL 60

Accepted Solution

by:
Kevin Cross earned 250 total points
ID: 22610200
Do you have an incrementing primary key (PK) or some other column that indicates a row is older than the one you are on?  If so, you could do something like this:


UPDATE MONEY 
SET Balance = Credit - Debit + 
IsNull((SELECT b.balance FROM MONEY b WHERE b.pkColumn IN (SELECT max(pkColumn) FROM MONEY c WHERE c.pkColumn < MONEY.pkColumn)), 0.00)

Open in new window

0
 
LVL 39

Assisted Solution

by:BrandonGalderisi
BrandonGalderisi earned 250 total points
ID: 22610767
I would POSSIBLY suggest not storing the balance then, if values are subject to change.  But that can be figured out

Or, you will have to run this frequently:

;with CurrentPast as
(select AccountNo, TransDate, Credit, Debit, cast(Null as money) as PreviousCredit, cast(Null as money) as PreviousDebit, row_number() over (partition by AccountNo order by TransDate) rn
from Money
union all
select mpAccountNo, mp.TransDate, mp.Credit, mp.Debit, row_number() over (partition by AccountNo order by TransDate) rn
from Money m
join CurrentPast cp
on m.accountNo = cp.AccountNo
and m.rn-1 = cp.rn)
select * from CurrentPast


^^ This will give you the each transaction as pairs. ^^


;with CurrentPast as
(select AccountNo, TransDate, Credit, Debit, cast(credit-debit as money) as CurrentChange, cast(0 as money) as PreviousBalance, row_number() over (partition by AccountNo order by TransDate) rn
from Money
union all
select mp.AccountNo, mp.TransDate, mp.Credit, mp.Debit, row_number() over (partition by AccountNo order by TransDate) rn
from Money m
join CurrentPast cp
on m.accountNo = cp.AccountNo
and m.rn-1 = cp.rn)



Now this is some sample code that shows you how to show a Running balance without ever changing it.  And it allows you to see a balance as of a point in time:



set nocount on
create table #tabMoney
(accountNo     int
,transDate     datetime
,Credit        money
,Debit         money
)
insert into #TabMoney values(1,'1/1/2007',0,20)
insert into #TabMoney values(1,'1/2/2007',20,0)
insert into #TabMoney values(1,'1/3/2007',0,15)
insert into #TabMoney values(1,'1/4/2007',10,0)
 
insert into #TabMoney values(2,'1/1/2007',0,100)
insert into #TabMoney values(2,'2/2/2007',0,50)
insert into #TabMoney values(2,'3/3/2007',160,0)
insert into #TabMoney values(2,'4/1/2007',0,10)
go
;with CurrentPast as
(
select t.* from 
(select AccountNo
     ,TransDate
     ,Credit
     ,Debit
     ,credit-debit as CurrentChange
     ,credit-debit as CurrentBalance
     ,row_number() over (partition by AccountNo order by TransDate) as rn
from #tabMoney) t
where t.rn=1
union all
select m.AccountNo, m.TransDate, m.Credit, m.Debit, m.CreditDebit, cp.CurrentChange+CreditDebit, m.rn
from 
     (select AccountNo
          ,TransDate
          ,Credit
          ,Debit
          ,credit-debit CreditDebit
          ,row_number() over (partition by AccountNo order by TransDate) rn
     from #tabMoney) m
  inner join CurrentPast cp
    on  m.accountNo = cp.AccountNo
    and m.rn-1 = cp.rn
)
select * from CurrentPast
Order by AccountNo,rn
go
drop table #tabMoney

Open in new window

0
 
LVL 39

Expert Comment

by:BrandonGalderisi
ID: 22610769
There are some assumptions based upon field names and structures.  But it can be easily adapted if you table structure is nothing like this.
0
Ransomware: The New Cyber Threat & How to Stop It

This infographic explains ransomware, type of malware that blocks access to your files or your systems and holds them hostage until a ransom is paid. It also examines the different types of ransomware and explains what you can do to thwart this sinister online threat.  

 
LVL 60

Expert Comment

by:Kevin Cross
ID: 22610891
I would agree with Brandon on not storing if you don't have to and if you want to use a common table expression and do have SQL 2005 you can modify the first query I gave you to do this:
WITH moneyCTE AS (
    SELECT *,
    row_number() over (ORDER BY transdate) AS rn
    FROM Money
)
UPDATE a
SET a.Balance = a.Credit - a.Debit + IsNull(b.balance, 0.00)
FROM moneyCTE a LEFT JOIN moneyCTE b
ON a.rn-1 = b.rn

Open in new window

0
 
LVL 60

Expert Comment

by:Kevin Cross
ID: 22610901
As Brandon, is saying here is he same query as a select instead of an update.
WITH moneyCTE AS (
    SELECT *,
    row_number() over (ORDER BY transdate) AS rn
    FROM Money
)
SELECT *, -- you can list out columns here
(a.Credit - a.Debit + IsNull(b.balance, 0.00)) AS newBalance
FROM moneyCTE a LEFT JOIN moneyCTE b
ON a.rn-1 = b.rn

Open in new window

0
 
LVL 39

Expert Comment

by:BrandonGalderisi
ID: 22610909
Same basic principal except I contained all of logic within the CTE to simplify the select.  6 & 1/2 dozen :)
0
 
LVL 60

Expert Comment

by:Kevin Cross
ID: 22610948
True.  Was just extending my query and at first glance your query looked much different with the union all statement, but I see now where you were going with that.

Regards,
Kev
0

Featured Post

Efficient way to get backups off site to Azure

This user guide provides instructions on how to deploy and configure both a StoneFly Scale Out NAS Enterprise Cloud Drive virtual machine and Veeam Cloud Connect in the Microsoft Azure Cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

PL/SQL can be a very powerful tool for working directly with database tables. Being able to loop will allow you to perform more complex operations, but can be a little tricky to write correctly. This article will provide examples of basic loops alon…
If you have heard of RFC822 date formats, they can be quite a challenge in SQL Server. RFC822 is an Internet standard format for email message headers, including all dates within those headers. The RFC822 protocols are available in detail at:   ht…
Come and listen to Percona CEO Peter Zaitsev discuss what’s new in Percona open source software, including Percona Server for MySQL (https://www.percona.com/software/mysql-database/percona-server) and MongoDB (https://www.percona.com/software/mongo-…
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…

696 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question