Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 Transact-SQL (2000)
 Balance calculations

Author  Topic 

carlossiwaily
Starting Member

24 Posts

Posted - 2007-11-21 : 20:57:18
Hello

I have a table as follow

T1(Tranid(pk),accountnumber,payin,payout, balance)


My problem is after insert how to update the balance Filed accordingly

If payin > 0 then

Update T1
Set balance = ( get balance of previous record where = accountnumber) + @payin
Where tranid = @@identity

Else if payout >0

Update t1
Set balance = ( get balance of previous record then where = accountnumber ) - @payin
Where tranid = @@identity


What I really want to achieve is to have same as bank statement

Date Payin payout Balance
20/11/2007 1000 0 1000
21/11/2007 0 500 500

Any help please

Many Thanks




carlossiwaily

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2007-11-21 : 23:04:33
Shouldn't you just take care of this on the inserts?

IF @payin > 0
INSERT INTO t1 (accountnumber, payin, payout, balance)
SELECT @acctno, @payin, @payout, balance + @payin
FROM t1
WHERE tranid = (SELECT MAX(tranid) FROM t1 WHERE accountnumber = @acctno)

IF @payout > 0
INSERT INTO t1 (accountnumber, payin, payout, balance)
SELECT @acctno, @payin, @payout, balance - @payin
FROM t1
WHERE tranid = (SELECT MAX(tranid) FROM t1 WHERE accountnumber = @acctno)

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/
Go to Top of Page

carlossiwaily
Starting Member

24 Posts

Posted - 2007-11-23 : 06:55:25
Hello Tara, Thanks for your help.. your solution solves my problem when the Tranid > 0 it all OK . But when the tranid = Null 0r 0 the balance + @payin = 0 at all time.
So i have used the following to solve the isuess.

IF @payin > 0
IF (SELECT MAX(tranid) FROM t1 WHERE accountnumber = @acctno)> 0

INSERT INTO t1 (accountnumber, payin, payout, balance)
SELECT @acctno, @payin, @payout, balance + @payin
WHERE tranid = (SELECT MAX(tranid) FROM t1 WHERE accountnumber = @acctno)
FROM t1
Else

INSERT INTO t1 (accountnumber, payin, payout, balance)
Values(@acctno, @payin, @payout, @payin)


Is there a better whys of solve the issue

Many Thanks

carlossiwaily
Go to Top of Page

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2007-11-23 : 17:30:33
You should save the MAX tranid value into a variable since you are using the same subquery twice. You'll get better performance this way since you won't have to grab that value twice.

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/
Go to Top of Page

georgev
Posting Yak Master

122 Posts

Posted - 2007-11-26 : 05:52:59
Correct me if I'm wrong, but shouldn't the balance be worked out on the fly rather than stored?

It would also be fairly simple to produce a query with a running sum total to make the results look like a bank statement.


George
<3Engaged!
Go to Top of Page

carlossiwaily
Starting Member

24 Posts

Posted - 2007-11-28 : 06:28:27
hi,
Many Thanks Tara for your help

Georgev, Yes you are right . that what i wanted but i really could not get it to work .. do you have any example?
Many Thanks.



carlossiwaily
Go to Top of Page

Jeff Moden
Aged Yak Warrior

652 Posts

Posted - 2007-12-01 : 21:42:50
quote:
It would also be fairly simple to produce a query with a running sum total to make the results look like a bank statement.



So, let's see it!

--Jeff Moden
Go to Top of Page

carlossiwaily
Starting Member

24 Posts

Posted - 2007-12-02 : 02:28:49
hello Georgev,

still waiting on your solution..

thanks

carlossiwaily
Go to Top of Page

carlossiwaily
Starting Member

24 Posts

Posted - 2007-12-22 : 13:13:17
hello,

any advice on how to create balance column on the fly or any samples how to create a bank statment.. I do not mind to pay for the code ..

many thanks

carlossiwaily
Go to Top of Page

Jeff Moden
Aged Yak Warrior

652 Posts

Posted - 2007-12-23 : 03:10:13
carlossiwaily,

How many rows and how many accounts do you have in your table that you need balances for?

--Jeff Moden
Go to Top of Page

carlossiwaily
Starting Member

24 Posts

Posted - 2007-12-23 : 13:36:44
Hello Jeff

Transactiontable(date, debit,credit,accountid)
This table will have transactions for over 1000 diffrent accounts, so this means the table will grow really big. i would like to provide my client with monthly statment for each account.

Can you please help .

Thanks

carlossiwaily
Go to Top of Page

TG
Master Smack Fu Yak Hacker

6065 Posts

Posted - 2007-12-23 : 14:03:58
Just to throw my 2 cents in:

I agree with georgev that you should not maintain a [balance] column in a detailed transaction table. Especially if the transaction table is written to often and under high concurrency. The customer statement (as a report) should handle the balance calculation. You only need to know the balance for that report, right? Not every time a transaction is written?

If that is the case your inserts become very easy. Depending on your reporting presentation layer you may be able to handle the balance calc in there. If you need help with a query to talley up the balance based on your transactions let us know.

Be One with the Optimizer
TG
Go to Top of Page

carlossiwaily
Starting Member

24 Posts

Posted - 2007-12-23 : 15:45:44
Hello

I have table

tran(Date,debit,credit,accountid)

data

12/12/2008,0,100,1

13/12/2008,0,200,1

14/12/2008,50,0,1

Now I want to achive the followoing using sql

1. Date Debit Credit, Balance

12/12/2008 0 100 100

13/12/2008 0 200 300

14/12/2008 50 0 250

How do i write sql qury to get the above result
for give accountid = 1

The result may return over 100,000 records so performance is very important

Many Thanks


carlossiwaily
Go to Top of Page

TG
Master Smack Fu Yak Hacker

6065 Posts

Posted - 2007-12-23 : 16:37:38
a couple questions:

- A bank statement usually is for a specific period, like 1 calendar month. Do you really need to return a complete history with every report? 100K row report is useless in my opinion.

- My bank statement just lists all the activity (without a rolling balance) then shows the beginning and ending balance. Is this an option for you or you need the rolling balance at each transaction?

- do you really only need to get the report for one account at a time?

EDIT:
I may reverse my (earlier stated) opinion about not storing the balance. If you really need to report a rolling balance at each transaction over 100K rows (for each account) then it may make more sense to store the value. Tara (tkizer) had a pretty good solution for doing that in the insert.

Be One with the Optimizer
TG
Go to Top of Page

TG
Master Smack Fu Yak Hacker

6065 Posts

Posted - 2007-12-23 : 17:09:08
This would probably be pretty slow over 100,000 rows but here is one option are two options for Sql2000 for getting a rolling balance:

create table #tran(tranid int identity(1,1), Date datetime,debit money,credit money,accountid int)

set dateformat 'dmy'
insert #tran (date, debit, credit, accountid)
select date, debit, credit, accountid
from (
select '12/12/2008' date ,0 debit ,100 credit, 1 accountid union all
select '13/12/2008',0,200,1 union all
select '14/12/2008',50,0,1
) a
order by date


select date
,debit
,credit
,balance =
(select sum(credit - debit)
from #tran
where accountid = a.accountid and tranid <= a.tranid)
from #tran a
where a.accountid = 1
order by tranid


--EDIT:
print 'alternate technique'
select a.date
,a.debit
,a.credit
,sum(b.credit - b.debit) balance
from #tran a
join #tran b
on a.accountid = b.accountid
and a.tranid >= b.tranid
group by a.accountid
,a.tranid
,a.date
,a.debit
,a.credit
order by a.accountid, a.tranid
--/EDIT

drop table #tran

output:
date debit credit balance
------------------------------------------------------------- --------------------- ---------------------
2008-12-12 00:00:00.000 .0000 100.0000 100.0000
2008-12-13 00:00:00.000 .0000 200.0000 300.0000
2008-12-14 00:00:00.000 50.0000 .0000 250.0000


Be One with the Optimizer
TG
Go to Top of Page

carlossiwaily
Starting Member

24 Posts

Posted - 2007-12-23 : 17:19:49
Many Thanks TG,

1. The Reports (statemts) can be per calendar month too.
2. It is better to show the balance at each transaction (as in real bank statment).
3. Yes, like to pass veriables fromdate, todate, accountid to the sql qury.

Well, to store the balance at each transaction has giveen me a lots of problems e.g when the user try to delete/edit a transaction then the value stored the balance column will all be incorect.

I would like to calculate the balance on fly

thanks for your help



carlossiwaily
Go to Top of Page

carlossiwaily
Starting Member

24 Posts

Posted - 2007-12-23 : 17:32:23
hello,

thank you very much for the code.. it works ok .. I would like the qury returns result per calender month. How would you calculate the correct balance .

Many thanks


carlossiwaily
Go to Top of Page

TG
Master Smack Fu Yak Hacker

6065 Posts

Posted - 2007-12-23 : 18:03:18
>>like to pass veriables fromdate, todate, accountid to the sql qury.
>>I would like the qury returns result per calender month. How would you calculate the correct balance

Here is one way:

create table #tran(tranid int identity(1,1), Date datetime,debit money,credit money,accountid int)

--set up sample data
set dateformat 'dmy'
insert #tran (date, debit, credit, accountid)
select date, debit, credit, accountid
from (
select '12/12/2008' date ,0 debit ,100 credit, 1 accountid union all
select '13/12/2008',0,200,1 union all
select '14/12/2008',50,0,1 union all
select '15/12/2008',0,200,1 union all
select '16/12/2008',50,0,1 union all
select '17/12/2008',0,200,1
) a
order by date


set dateformat 'ymd'

--input parameters
declare @fromDate datetime
,@toDate datetime
,@acctid int
select @fromDate = '2008-12-14'
,@toDate = '2008-12-15'
,@acctid = 1

--local variables
declare @begBal money, @begTranID int

--get the beginning tranID and Balance for earliest date up to (but not including) @fromDate
select @begBal = sum(credit - debit)
,@begTranID = max(tranid)
from #tran
where accountid = @acctid
and date < @fromDate


--Get details from @fromDate through @ToDate
select date
,debit
,credit
,balance = @begBal +
(select sum(credit - debit)
from #tran
where tranid > @begTranid
and accountid = a.accountid
and tranid <= a.tranid)
from #tran a
where a.accountid = @acctID
and tranid > @begTranid
and date <= @toDate

--EDIT:
print 'alternate technique - maybe faster?'
select a.date
,a.debit
,a.credit
,@begBal + sum(b.credit - b.debit) balance
from #tran a
join #tran b
on a.accountid = b.accountid
and a.tranid >= b.tranid
and b.tranid > @begTranid
where a.tranid > @begTranid
and a.date <= @toDate
group by a.accountid
,a.tranid
,a.date
,a.debit
,a.credit
order by a.accountid, a.tranid
--/EDIT

drop table #tran

output:
date debit credit balance
-------------------------------------------------------- --------------------- ---------------------
2008-12-14 00:00:00.000 50.0000 .0000 250.0000
2008-12-15 00:00:00.000 .0000 200.0000 450.0000


Be One with the Optimizer
TG
Go to Top of Page

Jeff Moden
Aged Yak Warrior

652 Posts

Posted - 2007-12-23 : 18:55:46
The problem with all of that is that the <= forms a triangular join. Right now, with the small number of records in the table (100,000), and 1,000 accounts, you only have an average of about 100 rows per account. Internally, that means that each of the 1000 accounts will generate (100*100+100)/2 rows or 5,050 rows for each account. Try that with a 1000 rows per account and see what you get.

Lemme know when you need something that will calculate a couple of million rows in a few seconds.

--Jeff Moden
Go to Top of Page

TG
Master Smack Fu Yak Hacker

6065 Posts

Posted - 2007-12-23 : 19:11:56
quote:
Originally posted by Jeff Moden

Lemme know when you need something that will calculate a couple of million rows in a few seconds.

Absolutely - by all means - don't just tease us I'm sure the OP would greatly appreciate it and I always like to see better ways to do stuff.

Be One with the Optimizer
TG
Go to Top of Page

Jeff Moden
Aged Yak Warrior

652 Posts

Posted - 2007-12-23 : 21:23:18
My applogies... I didn't mean to tease... didn't want to take the time to do the full demo if the OP doesn't need it. I'll work up the demo code and come back.

--Jeff Moden

(Edit) See next page for a 4,000,000 row example complete with a test data generator.
Go to Top of Page
    Next Page

- Advertisement -