An attempt to create a balance between debit and credit - sql

Well, I'll go directly to the case that is presented to me when trying to make a book with Extract and MUST HAVE in continuous BALANCE.
I was really hanging in my consultation, and I can not find any solution for desired.
Thanked would in some small contribution to some of you.
I'm looking for something like this:
ACCDATE ACCOUNT DEBIT CREDIT BALANCE
2013-01-01 00:00:00 11200 0.00 1500.00 -1500.00
2013-01-01 00:00:00 11200 0.00 60.00 -1560.00
2013-01-01 00:00:00 11200 0.00 400.00 -1960.00
2013-01-01 00:00:00 11200 0.00 100.00 -2060.00
2013-01-01 00:00:00 11200 0.00 300.00 -2360.00
2013-01-01 00:00:00 11200 0.00 250.00 -2910.00
OR:
ACCDATE ACCOUNT DEBIT CREDIT BALANCE
2013-01-01 00:00:00 11200 1500.00 0 1500.00
2013-01-01 00:00:00 11200 0.00 60.00 1440.00
2013-01-01 00:00:00 11200 0.00 400.00 1040.00
2013-01-01 00:00:00 11200 0.00 40 1000.00
2013-01-01 00:00:00 11200 300 0 1300.00
2013-01-01 00:00:00 11200 0.00 250.00 1550.00
I really do not require account type filter it by this time, but specific.
The idea is that with my Query still does not give me that result.
They can buy creating a provisional or temporary table with the same shown below:
INSERT INTO Accounting (AccDate,DebitCredit,Account,Amount) VALUES ('20110101','D',11200,1500)
INSERT INTO Accounting (AccDate,DebitCredit,Account,Amount) VALUES ('20110101','C',11200,60)
INSERT INTO Accounting (AccDate,DebitCredit,Account,Amount) VALUES ('20110102','D',11200,400)
INSERT INTO Accounting (AccDate,DebitCredit,Account,Amount) VALUES ('20110102','C',11200,100)
INSERT INTO Accounting (AccDate,DebitCredit,Account,Amount) VALUES ('20110102','C',11200,300)
INSERT INTO Accounting (AccDate,DebitCredit,Account,Amount) VALUES ('20110102','C',11200,250)
WITH CTE_FIRST AS
(
SELECT ACCDATE,
ACCOUNT,
CASE WHEN DEBITCREDIT='D' THEN AMOUNT ELSE 0 END AS DEBIT,
CASE WHEN DEBITCREDIT='C' THEN AMOUNT ELSE 0 END AS CREDIT,
ROW_NUMBER()OVER(ORDER BY ACCOUNT,ACCDATE) RN
FROM ACCOUNTING
WHERE ACCDATE >='20130101'
)
,CTE_SECOND AS(
SELECT *,
ISNULL((SELECT TOP 1 DEBIT FROM CTE_FIRST B WHERE B.ACCOUNT=A.ACCOUNT AND B.RN<A.RN ORDER BY RN DESC),0) COL1,
ISNULL((SELECT TOP 1 CREDIT FROM CTE_FIRST B WHERE B.ACCOUNT=A.ACCOUNT AND B.RN<A.RN ORDER BY RN DESC),0) COL2
FROM CTE_FIRST A
)
SELECT ACCDATE,ACCOUNT,DEBIT,CREDIT,
CASE WHEN DEBIT=0 THEN 0-(CREDIT+COL2) ELSE DEBIT+COL1 END BALANCE
FROM CTE_SECOND
Something happens in the validation of sum or not it's taking so linear consulting ....
All of this inquiry, I tried to help me with material that I got on the web. But it gives me the total response.

In the end I got this solution, but it becomes very slow the process.
Is there a way to optimize it?
Very slow for real, and it does not work for high queries.
DECLARE #T TABLE( FECHA DATETIME, COMENTARIO NVARCHAR (300), CUENTA
VARCHAR(15), DEBE NUMERIC(15,2), HABER NUMERIC(15,2) )
INSERT INTO #T SELECT FECHA, COMENTARIO, CUENTA, DEBE, HABER FROM
DIARIOAPUNTES;
/* INSERT INTO #T VALUES ('001-0001','20130102',100,0); INSERT INTO #T
VALUES ('001-0001','20130102',0,200); INSERT INTO #T VALUES
('001-0001','20130102',100,0); INSERT INTO #T VALUES
('001-0001','20130103',100,0); INSERT INTO #T VALUES
('001-0001','20130105',0,100); INSERT INTO #T VALUES
('001-0002','20130105',100,0); INSERT INTO #T VALUES
('001-0002','20130106',500,0);
*/
--DEBIT - CREDIT + BALANCE
WITH T_ROW AS (
SELECT (ROW_NUMBER() OVER(ORDER BY (T1_1.FECHA) ASC)) AS CONTADOR, FECHA, T1_1.CUENTA, T1_1.COMENTARIO, T1_1.DEBE, T1_1.HABER
FROM #T T1_1 )
SELECT T1.CONTADOR, T1.CUENTA, T1.COMENTARIO AS DESCRIPCION,
Convert(CHAR(10), T1.FECHA, 103) AS FECHA, T1.DEBE, T1.HABER,
ROUND(T1.DEBE-T1.HABER + COALESCE(T2.SALDO,0),2) AS SALDO FROM T_ROW
T1
CROSS APPLY(
SELECT ROUND(SUM(DEBE)-SUM(HABER),2) AS SALDO
FROM T_ROW T2
WHERE T2.CONTADOR < T1.CONTADOR AND T1.CUENTA = T2.CUENTA
) AS T2
--WHERE T1.FECHA BETWEEN '20130101' AND '20131231'
ORDER BY T1.CUENTA, T1.FECHA
--WHERE T1.ACCOUNTNO = '001-0001'

Related

Monthly Actual Cost vs Monthly Contract Amount

I have a project that pulls cost per category (labor, equipment, indirect), per month for a job and then shows a running, cumulative total of the contract amount per month. (This calculation is based on the total contract amount divided by the number of months in a project. Then the second month is the first month + second month, third month is first month + second month + third month, etc.)
I have the query shown below. When I run this, it returns the data shown under current results. What I need is the running total column populated even when there are no costs as shown under expected results. How do I accomplish this?
Current results:
fiscalMonth
Labor
Equipment
Indirect
RunningTotal
ContractPerMonth
2021-12-01
0.00
0.00
0.00
0.00
0.00
2022-01-01
6518.78
0.00
0.00
2141444.44
2141444.44
2022-02-01
8563.68
0.00
58.81
4282888.88
2141444.44
2022-03-01
7271.28
429.14
139167.21
6424333.32
2141444.44
2022-04-01
44538.32
2117.64
59379.53
8565777.76
2141444.44
2022-05-01
-14932.44
2476.85
1279972.38
10707222.20
2141444.44
2022-06-01
3701.65
250.00
992.45
12848666.64
2141444.44
2022-07-01
0.00
0.00
0.00
0.00
0.00
2022-08-01
0.00
0.00
0.00
0.00
0.00
Expected results:
fiscalMonth
Labor
Equipment
Indirect
RunningTotal
ContractPerMonth
2021-12-01
0.00
0.00
0.00
2141444.44
0.00
2022-01-01
6518.78
0.00
0.00
4282888.88
2141444.44
2022-02-01
8563.68
0.00
58.81
6424333.32
2141444.44
2022-03-01
7271.28
429.14
139167.21
8565777.76
2141444.44
2022-04-01
44538.32
2117.64
59379.53
10707222.20
2141444.44
2022-05-01
-14932.44
2476.85
1279972.38
12848666.64
2141444.44
2022-06-01
3701.65
250.00
992.45
14990111.08
2141444.44
2022-07-01
0.00
0.00
0.00
17131555.52
2141444.44
2022-08-01
0.00
0.00
0.00
19272999.96
0.00
Create Table #costs(fiscalMonth date, Labor numeric(12,2), Equipment numeric(12,2), Indirect numeric(12,2), RunningTotal numeric(12,2), ContractPerMonth numeric(12,2))
Declare #startDate as date, #endDate as date, #lastMonth as date,#count int
select #startDate = StartMonth, #endDate = ProjCloseDate from JCCM
WHERE
ltrim(rtrim(Contract)) = (#Job)
insert into #costs
SELECT
Mth
,isnull(Sum(LaborCost),0) as LaborCost
,Isnull(Sum(EquipmentCost),0) as EquipmentCost
,isnull(Sum(IndirectCost),0) as IndirectCost
,SUM (ContractAmtPerMonth) OVER (ORDER BY Mth) AS RunningTotal
,ContractAmtPerMonth
FROM(
SELECT
cp.Mth
,CASE WHEN ct.JBCostTypeCategory = 'L' THEN SUM(cp.ActualCost) END as LaborCost
,CASE WHEN ct.JBCostTypeCategory = 'E' THEN SUM(cp.ActualCost) END as EquipmentCost
,CASE WHEN ct.JBCostTypeCategory = 'O' THEN SUM(cp.ActualCost) END as IndirectCost
,(Select CASE WHEN Sum(cm.ContractAmt) <> 0 THEN CAST(SUM(cm.ContractAmt / ((DATEDIFF(Month,cm.StartMonth,cm.ProjCloseDate)+1))) as numeric(12,2)) END from JCCM cm WHERE cm.JCCo = jm.JCCo and cm.Contract = jm.Contract) as ContractAmtPerMonth
FROM
JCCP cp
LEFT JOIN JCCT ct ON cp.PhaseGroup = ct.PhaseGroup AND cp.CostType = ct.CostType
LEFT JOIN JCJM jm ON cp.JCCo = jm.JCCo and cp.Job = jm.Job
WHERE
cp.JCCo IN (#Company)
AND ltrim(rtrim(cp.Job)) = (#Job)
AND ct.JBCostTypeCategory IN ('L','E','O')
GROUP BY
jm.JCCo
,jm.Job
,jm.Contract
,cp.Mth
,ct.JBCostTypeCategory
)cost
GROUP BY
Mth
,ContractAmtPerMonth
WHILE (#startDate <= #endDate)
BEGIN
print CAST(#startDate AS VARCHAR(10)) + ' ' + CAST(#endDate AS VARCHAR(10))
select #count = Count (*) from #costs
print #count
if Not exists(select 1 from #costs where fiscalMonth = #startDate)
begin
insert into #costs (fiscalMonth, Labor, Equipment, Indirect,RunningTotal, ContractPerMonth ) values (#startDate,0,0,0,0,0)
end
set #startDate = DATEADD(month, 1, #startDate);
END
select * from #costs order by fiscalMonth
Drop table #costs
I was actually able to figure out how to accomplish what I needed. I modified how I created my table (changed table name from #costs to #months). This pulled the months, row number, and contract amount. I then joined it to my existing cost query. In SSRS, I'm able to calculate the running total by multiplying the monthly contract amount by the row number. Seems to be working.
create table #months (JCCo numeric, Job varchar(10), StartDate date, EndDate date)
insert into #months
SELECT JCCo,Contract,StartMonth, ProjCloseDate FROM JCCM WHERE JCCo = (#Company) AND Contract = (#Job);
with Q1 as
(
select JCCo,Job,StartDate as Mth
from #months
union all
select q.JCCo,q.Job,DATEADD(m, 1, q.Mth)
from Q1 q
inner join #months t on t.Job = q.Job
where Mth <= (DATEADD(MONTH,-1,t.EndDate))
)
select ROW_NUMBER() OVER ( order by Q1.Job, Q1.Mth) as Row#, Q1.JCCo, Q1.Job, Q1.Mth as fiscalMonth, ISNULL(cd.LaborCost,0) as Labor, ISNULL(cd.EquipmentCost,0) as Equipment, ISNULL(cd.IndirectCost,0) as Indirect, CAST(cm.ContractAmt / ((DATEDIFF(Month,cm.StartMonth,cm.ProjCloseDate)+1)) as DECIMAL(12,2)) as MonthlyContract, cm.ContractAmt as TotalContract
from Q1

query on mutiple transaction on same day

I am using sql server 2012..i have to get running balance on each row..now i am using below query
CREATE TABLE #Test(ID INT,TransDate datetime,Credit MONEY,[Debit] money)
INSERT INTO #Test
SELECT 1,'01/01/2017',10000,NULL UNION
SELECT 1,'01/05/2017',40000,NULL UNION
SELECT 1,'01/05/2017',200,NULL UNION
SELECT 1,'01/05/2017',200,NULL UNION
SELECT 1,'01/09/2017',NULL,45000 UNION
SELECT 2,'01/05/2017',1000,NULL UNION
SELECT 2,'01/06/2017',1000,NULL
SELECT t1.ID,convert(varchar,t2.TransDate,103) 'date',
t2.Credit,
t2.Debit,
SUM(COALESCE(t1.credit, 0) - COALESCE(t1.debit, 0)) AS Balance
FROM #Test t1
INNER JOIN #Test t2
ON t1.TransDate <= t2.TransDate
GROUP BY t1.ID,t2.TransDate , t2.Credit, t2.Debit
Output:
1 01/01/2017 10000.00 NULL 10000.00
1 05/01/2017 200.00 NULL 50200.00
1 05/01/2017 1000.00 NULL 50200.00
1 05/01/2017 40000.00 NULL 50200.00
1 06/01/2017 1000.00 NULL 50200.00
1 09/01/2017 NULL 45000.00 5200.00
2 05/01/2017 200.00 NULL 1000.00
2 05/01/2017 1000.00 NULL 1000.00
2 05/01/2017 40000.00 NULL 1000.00
2 06/01/2017 1000.00 NULL 2000.00
2 09/01/2017 NULL 45000.00 2000.00
Require Output:
Output:
1 01/01/2017 10000.00 NULL 10000.00
1 05/01/2017 200.00 NULL 10200.00
1 05/01/2017 1000.00 NULL 11200.00
1 05/01/2017 40000.00 NULL 50200.00
1 06/01/2017 1000.00 NULL 51200.00
1 09/01/2017 NULL 45000.00 5200.00
2 05/01/2017 200.00 NULL 200.00
2 05/01/2017 1000.00 NULL 1200.00
2 05/01/2017 40000.00 NULL 41200.00
2 06/01/2017 1000.00 NULL 42200.00
But if multiple entries for same tran day query does not work(see 2nd ,3rd & 4th row result).. it should not same ..Please any one help me to get the proper result?
Use a window function. This will work if the date column contains datetime...
select id,
TransDate,
credit,
debit,
sum(coalesce(credit,0)-coalesce(debit,0))
over (partition by id order by TransDate) as RunningBalance
from #Test
If the date column is date only, use:
with t1 as
(
select id,
TransDate,
credit,
debit,
row_number() over(partition by id, Transdate order by credit) as t_ord
from #Test
)
select id,
TransDate,
credit,
debit,
sum(coalesce(credit,0)-coalesce(debit,0))
over (partition by id order by TransDate, t_ord) as RunningBalance
from t1
First get date with required column and grop by date:
select A.TransDate, SUM(COALESCE(credit, 0)) as credit, SUM(COALESCE(debit, 0)) as debit, SUM(COALESCE(credit, 0) - COALESCE(debit, 0)) AS Balance from
(
SELECT convert(varchar,t2.TransDate, 103) as TransDate, t2.Credit, t2.Debit
FROM Test t1
INNER JOIN Test t2
ON t1.TransDate <= t2.TransDate
) as A group by A.TransDate
=================Or===============
With temp table:
select A.TransDate, SUM(COALESCE(credit, 0)) as credit, SUM(COALESCE(debit, 0)) as debit, SUM(COALESCE(credit, 0) - COALESCE(debit, 0)) AS Balance from
(
SELECT convert(varchar,t2.TransDate, 103) as TransDate, t2.Credit, t2.Debit
FROM Test #t1
INNER JOIN #Test t2
ON t1.TransDate <= t2.TransDate
) as A group by A.TransDate

SQL See Whether Two or More Columns In a Table is Greater Than 0

I have ran in to a little problem and would appreciate any help.
My Table is such:
CASH | CREDIT CARD | DEBIT CARD | ACCOUNT | OTHER
-------------------------------------------------
0.00 0.00 0.00 0.00 0.00
1.00 0.00 0.00 0.00 0.00
2.00 1.00 0.00 0.00 0.00
My aim is to SELECT * FROM any of the above rows that have more than one column > 0.
So the third row would be selected in this scenario with the above table.
SELECT
[CASH], [CREDIT CARD], [DEBIT CARD], [ACCOUNT], [OTHER]
FROM table
WHERE
CASE WHEN [CASH] > 0 THEN 1 ELSE 0 END+
CASE WHEN [CREDIT CARD] > 0 THEN 1 ELSE 0 END+
CASE WHEN [DEBIT CARD] > 0 THEN 1 ELSE 0 END+
CASE WHEN [ACCOUNT] > 0 THEN 1 ELSE 0 END+
CASE WHEN [OTHER] > 0 THEN 1 ELSE 0 END >= 2
I prefer t-clausen's answer but just as an exercise, I decide to try it as an UNPIVOT followed by a PIVOT, so that we could write it using more of the general SQL tools:
declare #t table (SomeID int,Cash money,Credit money,Debit money,Account money,Other money)
insert into #t(SomeID,Cash,Credit,Debit,Account,Other) values
(1,0.00,0.00,0.00,0.00,0.00),
(2,1.00,0.00,0.00,0.00,0.00),
(3,2.00,1.00,0.00,0.00,0.00)
;With Unpiv as (
select *,SUM(CASE WHEN MoneyValue > 0.00 THEN 1 ELSE 0 END) OVER (PARTITION BY SomeID) as cnt
from #t t
unpivot (MoneyValue for MoneyType in (Cash,Credit,Debit,Account,Other)) x
), Repiv as (
select *
from Unpiv u
pivot (SUM(MoneyValue) for MoneyType in (Cash,Credit,Debit,Account,Other)) x
where
cnt >= 2
)
select * from Repiv
This does assume that you've got another column (here, called SomeID) by which each row can be uniquely identified.
Result:
SomeID cnt Cash Credit Debit Account Other
----------- ----------- --------------------- --------------------- --------------------- --------------------- ---------------------
3 2 2.00 1.00 0.00 0.00 0.00
Just hoping the above might be more adaptable for some variants of the requirements.
SELECT
[CASH], [CREDIT CARD], [DEBIT CARD], [ACCOUNT], [OTHER]
FROM table
WHERE (
SELECT COUNT(*)
FROM (VALUES ([CASH]),([CREDIT CARD]),([DEBIT CARD]),([ACCOUNT]),([OTHER])) t(value)
WHERE value > 0
) >= 2

how to replace "Nothing" cell by last month value

I am using SSRS develop a report via Matrix.
I sum the product sales qty every month but if some month sale qty is 0, the cell will be Nothing.
I'm trying to using Previous function to solve problem but this function seems not work for Matrix object.
Is there any way to do this?
1st table is currently report result.
2nd table is that i want.
Assuming that you have a table with the structure and content like this:
CREATE TABLE a (date Date, product_name NVarchar(20), sale_qty Decimal(10,2))
INSERT INTO a (date, product_name, sale_qty) VALUES ('20130510','product A',1)
INSERT INTO a (date, product_name, sale_qty) VALUES ('20130601','product A',0)
INSERT INTO a (date, product_name, sale_qty) VALUES ('20130501','product B',5)
INSERT INTO a (date, product_name, sale_qty) VALUES ('20140205','product A',1)
INSERT INTO a (date, product_name, sale_qty) VALUES ('20140215','product A',1)
INSERT INTO a (date, product_name, sale_qty) VALUES ('20140202','product B',2)
INSERT INTO a (date, product_name, sale_qty) VALUES ('20140301','product A',0)
Then the below sql-statement will work for you (as far as I understood the requirement):
SELECT
y.Date2 AS 'yyyy/mm'
, y.product_name
, ISNULL(z.Month_sale_QTY,0) AS Month_sale_QTY
FROM
(SELECT
DATEADD(MONTH, x.number, y.StartDate) AS Date2
, (SELECT TOP 1 DATEADD(d,1-DATEPART(d,a.date),a.date) FROM a WHERE DATEADD(d,1-DATEPART(d,a.date),a.date) <= DATEADD(MONTH, x.number, y.StartDate) AND a.product_name = p.product_name AND ISNULL(a.sale_qty,0)<>0 ORDER BY 1 DESC) AS Date3
, p.product_name
FROM
master.dbo.spt_values x
INNER JOIN
(SELECT Dateadd(d,1-DATEPART(d, MIN(Date)), MIN(Date)) AS StartDate, MAX(Date) AS EndDate FROM a) AS y
ON x.number <= DATEDIFF(MONTH, y.StartDate, y.EndDate)
,(SELECT DISTINCT product_name FROM a) AS p WHERE x.type = 'P') y
LEFT JOIN
(SELECT
DATEADD(d,1-DATEPART(d,a.date),a.date) AS Date2
, a.product_name
, SUM(a.sale_qty) as Month_sale_QTY
FROM a
GROUP BY
DATEADD(d,1-DATEPART(d,a.date),a.date)
, a.product_name
) z ON y.Date3 = z.Date2 AND y.product_name = z.product_name
It returns the following:
yyyy/mm product_name Month_sale_QTY
---------- -------------------- ---------------------------------------
2013-05-01 product A 1.00
2013-06-01 product A 1.00
2013-07-01 product A 1.00
2013-08-01 product A 1.00
2013-09-01 product A 1.00
2013-10-01 product A 1.00
2013-11-01 product A 1.00
2013-12-01 product A 1.00
2014-01-01 product A 1.00
2014-02-01 product A 2.00
2014-03-01 product A 2.00
2013-05-01 product B 5.00
2013-06-01 product B 5.00
2013-07-01 product B 5.00
2013-08-01 product B 5.00
2013-09-01 product B 5.00
2013-10-01 product B 5.00
2013-11-01 product B 5.00
2013-12-01 product B 5.00
2014-01-01 product B 5.00
2014-02-01 product B 2.00
2014-03-01 product B 2.00
I'm sure it can be optimized using windowing functions and/or CTE, but as a quick solution this one will work too.

Impossible Task On Sql Calculation Where Date Is Equal

**
LOOK AT MY ANSWER WHICH IS REFERE AS NEW QUESTION ON SAME PROBLEM.
**
I have Confusion against utilize If,Else Statement against calculation of stock By date. And sort the same by date.
There is real challenge to calculate running total between equal date:
If date is equal
If date is greater than
If date is less than
My Table Schema Is:
TransID int, Auto Increment
Date datetime,
Inwards decimal(12,2)
Outward decimal(12,2)
Suppose If I have Records as Below:
TransID Date(DD/MM/YYYY) Inward Outward
1 03/02/2011 100
2 12/04/2010 200
3 03/02/2011 400
Than Result Should be:
TransID Date(DD/MM/YYYY) Inward Outward Balance
2 12/04/2010 200 -200
1 03/02/2011 100 -300
3 03/02/2011 400 100
I wants to calculate Inward - outwards = Balance and Balance count as running total as above. but the condition that it should be as per date order by Ascending
How to sort and calculate it by date and transID?
What is transact SQL IN SQL_SERVER-2000**?.
You can use a brute O(n2) approach of self-joining the table to itself, or if the table is large, it is better to iteratively calculate the balance. The choices for SQL Server 2000 are limited, but the approach I will show uses a loop that traverses the table in date, transid order rather than using cursors.
Here is a sample table for discussion
create table trans (transid int identity, date datetime, inwards decimal(12,2), outward decimal(12,2))
insert trans select '20110203', null, 100
insert trans select '20100412', null, 200
insert trans select '20110203', 400, null -- !same date as first
This is the T-SQL batch that will give you the output you require. If you merely wanted to update a balance column in the table (if it had such an extra column), change all references to #trans to the table itself.
-- fill a temp table with the new column required
select *, cast(null as decimal(12,2)) as balance
into #trans
from trans
-- create an index to aid performance
create clustered index #cix_trans on #trans(date, transid)
-- set up a loop to go through all record in the temp table
-- in preference to using CURSORs
declare #date datetime, #id int, #balance decimal(12,2)
select top 1 #date = date, #id = transid, #balance = 0
from #trans
order by date, transid
while ##ROWCOUNT > 0 begin
update #trans set #balance = balance = #balance + coalesce(inwards, -outward)
where transid = #id
-- next record
select top 1 #date = date, #id = transid
from #trans
where (date = #date and transid > #id)
or (date > #date)
order by date, transid
end
-- show the output
select *
from #trans
order by date, transid
;
-- clean up
drop table #trans;
Output
2 2010-04-12 00:00:00.000 NULL 200.00 -200.00
1 2011-02-03 00:00:00.000 NULL 100.00 -300.00
3 2011-02-03 00:00:00.000 400.00 NULL 100.00
EDIT
If you need to show the final output using the date formatted to dd/mm/yyyy, use this
-- show the output
select transid, convert(char(10), date, 103) date, inwards, outward, balance
from #trans
order by #trans.date, transid
;
Is Balance (Inward-Outward) ?
select TransID,
Date,
Inward,
Outward,
(select sum(Inward - Outward)
from tbl_name b1
where b1.TransID <= b.TransID) as RunB
from tbl_name b
order by Date desc,TransID desc
This would order by Date in descending order - if the dates are same they are ordered by TransID
Edit:
Assume a Transaction table as this
select * from Transactions
1 NULL 100.00 2010-01-01 00:00:00.000
2 NULL 200.00 2010-01-02 00:00:00.000
3 400.00 NULL 2010-01-03 00:00:00.000
4 50.00 NULL 2010-01-03 00:00:00.000
5 NULL 100.00 2010-01-04 00:00:00.000
If you do this query ie, sort by TransactionIDs you would get this!
select TransID,
Date,
isNull(Inward,0.0),
isNull(Outward,0.0),
(select sum(isNull(Inward,0.0) - isNull(Outward,0.0))
from Transactions b1
where b1.TransID <= b.TransID) as RunB
from Transactions b
order by Date asc,TransID asc
1 2010-01-01 00:00:00.000 0.00 100.00 -100.00
2 2010-01-02 00:00:00.000 0.00 200.00 -300.00
3 2010-01-03 00:00:00.000 400.00 0.00 100.00
4 2010-01-03 00:00:00.000 50.00 0.00 150.00
5 2010-01-04 00:00:00.000 0.00 100.00 50.00
Instead if you use this query - sort by date you would get this? Is this what you meant Mahesh?
select TransID,
Date,
isNull(Inward,0.0),
isNull(Outward,0.0),
(select sum(isNull(Inward,0.0) - isNull(Outward,0.0))
from Transactions b1
where b1.Date <= b.Date) as RunB
from Transactions b
order by Date asc,TransID asc
1 2010-01-01 00:00:00.000 0.00 100.00 -100.00
2 2010-01-02 00:00:00.000 0.00 200.00 -300.00
3 2010-01-03 00:00:00.000 400.00 0.00 150.00
4 2010-01-03 00:00:00.000 50.00 0.00 150.00
5 2010-01-04 00:00:00.000 0.00 100.00 50.00
The difference in queries being -> (b1.Date <= b.Date) and (b1.TransID <= b.TransID)
Take this first bit of cyberkiwi's solution:
select *, cast(null as decimal(12,2)) as balance
into #trans
from stock
and change it so the nvarchar dates from your table are converted to datetime values. That is, expand the * into the actual set of columns, replacing the date column with the converting expression.
Given the structure you've shown in your original question, it may look like this:
select
TransID,
convert(datetime, substring(Date,7,4) + substring(Date,4,2) + substring(Date,1,2)) as Date,
Inward,
Outward,
cast(null as decimal(12,2)) as balance
into #trans
from stock
Leave the rest of the script untouched.
Now this is Solution with date in format dd/MM/yyyy of above question.
select *, cast(null as decimal(12,2)) as balance
into #trans
from stock
-- create an index to aid performance
create clustered index #cix_trans on #trans(date, transid)
--set up a loop to go through all record in the temp table
-- in preference to using CURSORs
declare #date datetime, #id int, #balance decimal(12,2)
select top 1 #date = date, #id = transid, #balance = 0
from #trans
order by date, transid
while ##ROWCOUNT > 0 begin
update #trans set #balance = balance = #balance + coalesce(input, -output)
where transid = #id
-- next record
select top 1 #date = date, #id = transid
from #trans
where (date = #date and transid > #id)
or (date > #date)
order by date, transid
end
-- show the output
select
transID,
date= convert(varchar,convert(datetime,date,103),103),
input,
output,
balance
from #trans
order by convert(datetime,date,103), transID
-- clean up
drop table #trans;