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
Related
I have Attached one Image and i want 7800-2000=5800 with based on under group last rows total sum using sql server query
i want output like this
GroupName Credit Debit DrCrEffect UnderGroupName Total
Opening Balance 0.00 0.00 Dr Master Group NULL
Opening Stock 0.00 0.00 Dr Opening Stock NULL
Purchase 0.00 7800.00 Dr Purchase 0.00
Purchase Return 2000.00 0.00 Dr Purchase 5800
Query:
SELECT MAG.GroupName,
SUM(isnull(tm.Credit,0.00))Credit,
SUM(ISNULL(TM.Debit,0.00))Debit,
mag.DrCrEffect,
MAG.UnderGroupName,
SUM(TM.Credit-tm.Debit)Total
FROM dbo.Mst_Account_Group MAG
LEFT JOIN dbo.Party P ON MAG.Mst_Account_Group_Id = P.Mst_Account_Group_Id
AND mag.EffectTo='Trading Account' AND MAG.DrCrEffect='dr'
LEFT JOIN dbo.Transaction_Master TM ON tm.Ledger_Id=p.Party_Id
WHERE P.Company_Id=1 AND P.Branch_Id=1
GROUP BY mag.GroupName, mag.DrCrEffect, MAG.UnderGroupName
You can use LAG function to achieve this. LAG will give you the value from previous row in the current row selection.
declare #table table (groupname varchar(50),
credit numeric(18,2),
debit numeric(18,2),
drcreffect varchar(50),
undergroup varchar(50))
insert into #table values
('Opening Balance', 0.00 , 0.00 ,'Dr', 'Master Group' ),
('Opening Stock', 0.00 , 0.00 ,'Dr', 'Opening Stock' ),
('Purchase', 0.00 , 7800.00 ,'Dr', 'Purchase'),
('Purchase Return', 2000.00, 0.00 ,'Dr', 'Purchase')
select groupname,
credit,
debit,
drcreffect,
undergroup,
LAG(debit,1,0) OVER (ORDER BY groupname)-credit AS Total
from #table
Output:
Note: Replace #table with your actual table name.
Update:
declare #table table (groupname varchar(50),
credit numeric(18,2),
debit numeric(18,2),
drcreffect varchar(50),
undergroup varchar(50))
insert into #table values
('Opening Balance', 0.00 , 0.00 ,'Dr', 'Master Group' ),
('Opening Stock', 0.00 , 0.00 ,'Dr', 'Opening Stock' ),
('Purchase', 0.00 , 7800.00 ,'Dr', 'Purchase'),
('Purchase Return', 2000.00, 0.00 ,'Dr', 'Purchase'),
('Purchase Return', 3000.00, 0.00 ,'Dr', 'Purchase'),
('Sales', 0.00, 5000.00 ,'Dr', 'Sales'),
('Sales Return', 2000.00, 0.00 ,'Dr', 'Sales'),
('Sales Return', 2000.00, 0.00 ,'Dr', 'Sales')
SELECT groupname,credit,debit,drcreffect,undergroup, LAG(debit,1,0) OVER (ORDER BY groupname)-credit AS Total from (
SELECT DISTINCT groupname,SUM(credit) OVER(PARTITION BY groupname) AS Credit,SUM(debit) OVER(PARTITION BY groupname) AS debit,drcreffect,undergroup
FROM #table ) X
I have court clearance statistic to made, but i have some slight problem with my monthly.. it didt follow in order, and wish someone could help me fix it.. and is it possible to add total in my table?
DECLARE #StartDate As date = '03-28-2015',
#EndDate As date = '03-28-2015'
DECLARE #TEMP_DATES AS TABLE (FROM_DATE DATE, TO_DATE DATE)
INSERT INTO #TEMP_DATES VALUES(#StartDate, #EndDate)
DECLARE #TENP_MONTH_YEAR AS TABLE(MONTH_YEAR VARCHAR(20), [YEAR] INT, [MONTH] INT)
INSERT INTO #TENP_MONTH_YEAR
select FORMAT(D.Dates, 'MMMM-yy', 'en-US' ) AS MonthYear, YEAR(D.Dates), MONTH(D.Dates)
from #TEMP_DATES as T
inner join master..spt_values as N
on N.number between 0 and datediff(DAY, T.FROM_DATE, T.TO_DATE)
cross apply (select dateadd(DAY, N.number, T.FROM_DATE)) as D(Dates)
where N.type ='P'
GROUP BY FORMAT(D.Dates, 'MMMM-yy', 'en-US' ), YEAR(D.Dates), MONTH(D.Dates)
ORDER BY YEAR(D.Dates), MONTH(D.Dates)
DECLARE #NEWID AS UNIQUEIDENTIFIER = NEWID()
SELECT CT.RPT_CASE_CODE_GROUP, SUM(ISNULL(INCOMING_CASES, 0)) AS INCOMING_CASES, SUM(ISNULL(OUTGOING_CASES, 0)) AS OUTGOING_CASES,
ISNULL(CAST(SUM(NULLIF(CAST(ISNULL(OUTGOING_CASES, 0) AS DECIMAL),0.00))/SUM(NULLIF(CAST(ISNULL(INCOMING_CASES, 0) AS DECIMAL),0.00)) * 100 AS DECIMAL(18,2)),0) AS [CLEARANCE_RATE],
MONTH_YEAR
FROM #tempClearanceListCases tempCLC
RIGHT OUTER JOIN (SELECT CASE_TYPE_ID, MONTH_YEAR, [YEAR], [MONTH]
FROM (SELECT DISTINCT CASE_TYPE_ID FROM #tempClearanceListCases tempCLC ) A, #TENP_MONTH_YEAR tempMonthYear) B
ON B.CASE_TYPE_ID = tempCLC.CASE_TYPE_ID AND tempCLC.MONTHLY = B.MONTH_YEAR
INNER JOIN CaseType CT WITH (NOLOCK)
ON B.CASE_TYPE_ID = CT.CASE_TYPE_ID
WHERE ISNULL(COURT_LOCATION_ID, #NEWID) = ISNULL(#COURT_LOCATION_ID, ISNULL(COURT_LOCATION_ID, #NEWID))
GROUP BY CT.RPT_CASE_CODE_GROUP, [INTERVAL_MONTH], MONTH_YEAR
ORDER BY CT.RPT_CASE_CODE_GROUP
The result which is the monthly is not correct order:
RPT_CASE_CODE_GROUP | INCOMEING CASES | OUTGOING CASES | CLEARANCERATE | MONTHYEAR
BCY/CP 15 4 26.67 March-15
BCY/CP 15 0 0.00 February-15
BCY/CP 33 0 0.00 January-15
BCY/DP 0 0 0.00 February-15
BCY/DP 2 0 0.00 March-15
BCY/DP 1 0 0.00 January-15
The result atleast i want it to be :
RPT_CASE_CODE_GROUP | INCOMEING CASES | OUTGOING CASES | CLEARANCERATE | MONTHYEAR
BCY/CP 33 0 0.00 January-15
BCY/CP 15 0 0.00 February-15
BCY/CP 15 4 26.67 March-15
BCY/DP 1 0 0.00 January-15
BCY/DP 0 0 0.00 February-15
BCY/DP 2 0 0.00 March-15
The result i want :
RPT_CASE_CODE_GROUP | INCOMEING CASES | OUTGOING CASES | CLEARANCERATE | MONTHYEAR
BCY/CP 33 0 0.00 January-15
BCY/CP 15 0 0.00 February-15
BCY/CP 15 4 26.67 March-15
63 4 6.34 Overall
BCY/DP 1 0 0.00 January-15
BCY/DP 0 0 0.00 February-15
BCY/DP 2 0 0.00 March-15
3 0 0.00 Overall
DO i have to stick to my query or create grouping query? i already spend many hour on this, i feel hard to turn back, im fresh grad :( can any guru guide me?
if all your MONTHYEAR are following the sames patter monthname-xx you can use following statement on order:
ORDER BY
cast('20' + substring(MONTHYEAR, Charindex('-', MONTHYEAR) + 1, 2) + '-' + substring(MONTHYEAR, 1, 3) + '-01' AS date)
This looks like a job for the UNION clause. It seems like you should have this execution order for the results you want:
SELECT -- data you want from tables w/ all joins
WHERE RPT_CASE_CODE_GROUP = 'BCY/CP'
UNION ALL
SELECT '', SUM([INCOMING CASES]), SUM([OUTGOING CASES]), AVG([CLEARANCE RATE], 'Overall'
FROM -- source data
WHERE RPT_CASE_CODE_GROUP = 'BCY/CP'
UNION ALL
SELECT -- data you want from tables w/ all joins
WHERE RPT_CASE_CODE_GROUP = 'BCY/DP'
UNION ALL
SELECT '', SUM([INCOMING CASES]), SUM([OUTGOING CASES]), AVG([CLEARANCE RATE], 'Overall'
FROM -- source data
WHERE RPT_CASE_CODE_GROUP = 'BCY/CP'
Alternatively, if there are more RPT_CASE_CODE_GROUP values than the one presented, you can use a loop to capture information about all of them like this:
CREATE TABLE #rccg(ID INT IDENTITY(1,1), RPT_CASE_CODE_GROUP NVARCHAR(15))
INSERT INTO #rccg(RPT_CASE_CODE_GROUP)
SELECT DISTINCT RPT_CASE_CODE_GROUP FROM --data source
DECLARE #i INT = 1, #j INT = (SELECT MAX(ID) FROM #rccg), #rccg NVARCHAR(15)
DECLARE #results TABLE(rccg NVARCHAR(15), ic INT, oc INT, cr INT, my NVARCHAR(20))
WHILE #i < #j
BEGIN
SET #rccg = (SELECT RPT_CASE_CODE_GROUP FROM #rccg WHERE ID = #i)
INSERT INTO #results
SELECT -- data you want from tables w/ all joins
WHERE RPT_CASE_CODE_GROUP = #rccg
UNION ALL
SELECT '', SUM([INCOMING CASES]), SUM([OUTGOING CASES]), AVG([CLEARANCE RATE], 'Overall'
FROM -- source data
WHERE RPT_CASE_CODE_GROUP = #rccg
END
SELECT * FROM #rccg
DROP TABLE #rccg
I know I didn't use your specific code, because that would have taken up a huge amount of space, but I think you get the general idea. For each field you want the totals of for the time period, you use the SUM(column_name) aggregate function. You can get a pretty good explanation and examples here: http://www.techonthenet.com/sql/sum.php.
I hope this at least helps point you in the right direction.
The below query gets customer statement:
SELECT t.S_Type,t.Number, t.Debit, t.Credit,t.CustID,b.Balance
FROM Statement as t
CROSS apply
(
SELECT Balance = SUM(Debit) - SUM(Credit)
FROM Statement as x
WHERE x.Number<= t.Number
) b
ORDER BY t.Number
Query result:
type # Debit credit cid balance
Sales Invoice 1 200.00 0.00 3 200.00
Sales Invoice 10 850.00 0.00 3 1050.00
Service Invoice 11 90.00 0.00 21 1140.00
Sales Invoice 12 20.00 0.00 3 1160.00
Sales Invoice 13 200.00 0.00 2 1360.00
Sales Invoice 14 20.00 0.00 9 1380.00
Sales Invoice 15 120.00 0.00 17 1500.00
Sales Invoice 16 100.00 0.00 19 1600.00
Sales Invoice 17 140.00 0.00 20 1740.00
Sales Invoice 18 4250.00 0.00 16 5990.00
Sales Invoice 19 2500.00 0.00 22 8490.00
Sales Invoice 2 100.00 0.00 7 8590.00
Sales Invoice 20 1225.00 0.00 2 9815.00
Sales Invoice 3 200.00 0.00 1 10015.00
Sales Invoice 4 520.00 0.00 2 10535.00
Sales Invoice 5 25.00 0.00 1 10560.00
Sales Invoice 6 160.00 0.00 2 10720.00
Sales Invoice 7 20.00 0.00 7 10740.00
Sales Invoice 9 850.00 0.00 2 11590.00
But I'd like to get the statement for customer with id 7. The query I use for this is:
SELECT t.S_Type,t.Number, t.Debit, t.Credit,t.CustID,b.Balance
FROM Statement as t
CROSS apply
(
SELECT Balance = SUM(Debit) - SUM(Credit)
FROM Statement as x
WHERE x.Number<= t.Number
) b
where t.CustID='7'
ORDER BY t.Number
This query's result is:
type # Debit credit cid balance
Sales Invoice 2 100.00 0.00 7 8590.00
Sales Invoice 7 20.00 0.00 7 10740.00
However, that result is wrong. I expect it to be:
balance
100.00
120.00
What's wrong with the query?
To fix your query you need to add the CustID to the correlated cross apply so that the sum only is calculated for the customer in the outer scope and not for all:
SELECT t.S_Type, t.Number, t.Debit, t.Credit, t.CustID, b.Balance
FROM Statement AS t
CROSS APPLY
(
SELECT Balance = SUM(Debit) - SUM(Credit)
FROM Statement AS x
WHERE x.Number <= t.Number AND t.CustID = x.CustID
) b
WHERE t.CustID='7'
ORDER BY t.Number
If you're using SQL Server 2012+ a better alternative that also should perform better would be to use sum() as a window function:
SELECT
S_Type, Number, Debit, Credit, CustId,
Balance = SUM(Debit - Credit) OVER (PARTITION BY CustId ORDER BY Number)
FROM Statement
WHERE CustID='7'
ORDER BY Number
Your original query (without the where clause) would be:
SELECT
S_Type, Number, Debit, Credit, CustID,
Balance = SUM(Debit - Credit) OVER (ORDER BY number)
FROM Statement
ORDER BY Number
In CROSS APPLY add following in the WHERE:
AND x.CustID = t.CustID
Finally I got what you need. To make this you need to filter by customer also. Otherwise the cumulative balance is made on whole set and after that you show only customer 7.
After the change you will have cumulative balance only for customer 7.
Proper SQL:
SELECT t.S_Type,t.Number, t.Debit, t.Credit,t.CustID,b.Balance
FROM Statement as t
CROSS apply
(
SELECT Balance = SUM(Debit) - SUM(Credit)
FROM Statement as x
WHERE x.Number<= t.Number and x.CustID = t.CustID
) b
where t.CustID='7'
ORDER BY t.Number
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
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'