Cumulative total based off of two columns - sql

So I am looking to get an extra column into my query that calculates a cumulative balance based off of the credit/debit columns.
My query looks like this so far:
SELECT T1.[RefDate], T1.[TransId], T1.[BaseRef], T1.[LineMemo], T3.[Dscription], T1.[Debit], T1.[Credit], T4.[AcctName]
FROM OJDT T0
right JOIN JDT1 T1 ON T0.TransId = T1.TransId
left JOIN OPCH T2 ON T0.TransId = T2.TransId
left JOIN PCH1 T3 ON T3.DocEntry = T2.DocEntry
left JOIN OACT T4 ON T1.Account = T4.AcctCode
WHERE T4.[AcctCode] = [%0] AND
T1.[RefDate] BETWEEN [%1] AND [%2]

You could use windowed SUM:
SELECT T1.[RefDate], T1.[TransId], T1.[BaseRef], T1.[LineMemo], T3.[Dscription],
T1.[Debit], T1.[Credit], T4.[AcctName],
SUM(ISNULL(Debit,0)+ISNULL(Credit,0)) OVER(PARTITION BY ... ORDER BY refDate)
FROM OJDT T0
right JOIN JDT1 T1 ON T0.TransId = T1.TransId
left JOIN OPCH T2 ON T0.TransId = T2.TransId
left JOIN PCH1 T3 ON T3.DocEntry = T2.DocEntry
left JOIN OACT T4 ON T1.Account = T4.AcctCode
WHERE T4.[AcctCode] = [%0] AND
T1.[RefDate] BETWEEN [%1] AND [%2];
If Debit column contains positive values you need to prefix it with -.

Documentation around OVER: https://msdn.microsoft.com/en-us/library/ms189461(v=SQL.110).aspx
You'll probably find example C to be the most useful though it looks like you don't want to PARTITION, you want to use RANGE.
you'll want something like this for your calculated column:
SUM(ISNULL(Debit,0)+ISNULL(Credit,0))
OVER(RANGE UNBOUNDED PRECEDING AND CURRENT ROW) AS RunningTotal
This will result in a query something like:
SELECT T1.[RefDate], T1.[TransId], T1.[BaseRef], T1.[LineMemo], T3.[Dscription], T1.[Debit], T1.[Credit], T4.[AcctName],
SUM(ISNULL(Debit,0)+ISNULL(Credit,0))
OVER(RANGE UNBOUNDED PRECEDING AND CURRENT ROW) AS RunningTotal
FROM OJDT T0
right JOIN JDT1 T1 ON T0.TransId = T1.TransId
left JOIN OPCH T2 ON T0.TransId = T2.TransId
left JOIN PCH1 T3 ON T3.DocEntry = T2.DocEntry
left JOIN OACT T4 ON T1.Account = T4.AcctCode
WHERE T4.[AcctCode] = [%0] AND
T1.[RefDate] BETWEEN [%1] AND [%2]

Related

multiple inner joins in bigquery result in duplicated rows

Im tryin to join 6 tables in bigquery named
T0, T1, T2, T3, T4, T5
The tables result im interested are T0 and T1
after query this tables I got 43 matches
SELECT
T1.F1,
T0.F2,
T0.F3,
T0.F4,
T1.F5,
T1.F6,
T1.F7,
T1.F8
T0.F9
FROM `TABLE0` T0
INNER JOIN `TABLE1` T1 on T1.F1= T0.F1
WHERE T0.F1 = "010001476713"
AND T0.F2 = T1.F2
ORDER BY T0.F4
But when I run this with multiple INNER JOIN I got 800 results not the 43, results are duplicated
SELECT
T2.F11,
T3.F15,
T2.F12,
T3.F16,
T3.F17,
T1.F1,
T2.F13,
T3.F17,
T5.F18,
T5.F19,
T5.F20,
T2.F14,
T0.F9,
T1.F10,
T4.F3,
T4.F21,
T4.F22,
T0.F2,
T3.F23,
T0.F3,
T0.F4,
T1.F5,
T1.F6,
T1.F7,
T1.F8
FROM `TABLE0` T0
INNER JOIN `TABLE1` T1 ON T1.F1= T0.F1
INNER JOIN `TABLE3` T3 ON T3.F1=T1.F1
INNER JOIN `TABLE2` T2 ON T2.F24 = T3.F24
INNER JOIN `TABLE4` T4 ON T4.F3 = T0.F3
INNER JOIN `TABLE5` as T5 ON T5.F1=T0.F1
WHERE T0.F1 = "010001476713"
AND T0.F2 = T1.F2
ORDER BY T0.F4
When I get duplicate rows, I solve it like this:
You get 43 results on your inner join of table T0 & T1. So far so good.
Now comment out everything related to table T2, T4, & T5 (I've placed the commas at the beginning of the row for easier commenting out) like this
SELECT
--T2.F11,
T3.F15
--,T2.F12
,T3.F16
,T3.F17
,T1.F1
--,T2.F13
,T3.F17
--,T5.F18
--,T5.F19
--,T5.F20
--,T2.F14
,T0.F9
,T1.F10
--,T4.F3
--,T4.F21
--,T4.F22
,T0.F2
,T3.F23
,T0.F3
,T0.F4
,T1.F5
,T1.F6
,T1.F7
,T1.F8
FROM `TABLE0` T0
INNER JOIN `TABLE1` T1 ON T1.F1= T0.F1 and T0.F2 = T1.F2
INNER JOIN `TABLE3` T3 ON T3.F1=T1.F1
--INNER JOIN `TABLE2` T2 ON T2.F24 = T3.F24
--INNER JOIN `TABLE4` T4 ON T4.F3 = T0.F3
--INNER JOIN `TABLE5` as T5 ON T5.F1=T0.F1
WHERE T0.F1 = "010001476713"
ORDER BY T0.F4
I've moved the and T0.F2 = T1.F2 from the where to on in the inner join. When you run this query, do you still get 43 rows, or more? If more, you need to figure out what it is double matching on, and add that to your on statement of it really is a 1-1 relationship, or perhaps group the results if you don't want multiple matches. You may need to comment out your select statement and select all to really figure it out, like this:
SELECT *
/*
--T2.F11,
T3.F15
--,T2.F12
,T3.F16
,T3.F17
,T1.F1
--,T2.F13
,T3.F17
--,T5.F18
--,T5.F19
--,T5.F20
--,T2.F14
,T0.F9
,T1.F10
--,T4.F3
--,T4.F21
--,T4.F22
,T0.F2
,T3.F23
,T0.F3
,T0.F4
,T1.F5
,T1.F6
,T1.F7
,T1.F8
*/
FROM `TABLE0` T0
INNER JOIN `TABLE1` T1 ON T1.F1= T0.F1 and T0.F2 = T1.F2
INNER JOIN `TABLE3` T3 ON T3.F1=T1.F1
--INNER JOIN `TABLE2` T2 ON T2.F24 = T3.F24
--INNER JOIN `TABLE4` T4 ON T4.F3 = T0.F3
--INNER JOIN `TABLE5` as T5 ON T5.F1=T0.F1
WHERE T0.F1 = "010001476713"
ORDER BY T0.F4
Once you figure out what rows are causing the duplication, you either group the results or add an 'and' statement to the on clause to make it a 1-1, and then move on. You then uncomment the parts of the query related to T2 and do the same thing, then T4 and then T5. If you send me the results of the query above, I can help you figure out what your on clause needs to be to keep it from duplicating.
thank you #jenstretman, I find table 4 to be duplicating matches by using a foreign Key with non-primary Key creating duplicates, the solution was to use a DISTINCT to only select specifically matched rows.
SELECT DISTINCT
T2.F11,
T3.F15,
T2.F12,
T3.F16,
T3.F17,
T1.F1,
T2.F13,
T3.F17,
T5.F18,
T5.F19,
T5.F20,
T2.F14,
T0.F9,
T1.F10,
T4.F3,
T4.F21,
T4.F22,
T0.F2,
T3.F23,
T0.F3,
T0.F4,
T1.F5,
T1.F6,
T1.F7,
T1.F8
FROM `TABLE0` T0
INNER JOIN `TABLE1` T1 ON T1.F1= T0.F1
INNER JOIN `TABLE3` T3 ON T3.F1=T1.F1
INNER JOIN `TABLE2` T2 ON T2.F24 = T3.F24
INNER JOIN (SELECT DISTINCT T4.F3, T4.F21, T4.F22, FROM `TABLE4` T4)T4 ON T4.F3 = T0.F3
INNER JOIN `TABLE5` as T5 ON T5.F1=T0.F1
WHERE T0.F1 = "010001476713"
AND T0.F2 = T1.F2
ORDER BY T0.F4

How do I get this Right outer join to work?

I'm attempting to show all sales orders and, if they have them, the delivery note. I've got a query showing all orders but no matter how I join it to the next table, I continue to get results for only orders with delivery notes. I want NULL to be present for delivery notes if there are none on record.
I've tried left, right, and inner joins and they're all returning the same number of results which baffles me. I thought I had an understanding of joins before today.
This part shows how many sales orders exist. I want all results from this to appear in the next query
select t0.docnum SalesOrder, t1.itemcode, t1.linenum rdr1line
from ordr t0 inner join rdr1 t1 on t1.docentry = t0.docentry
where t0.CANCELED = 'N';
This part shows how many sales orders exist with a Delivery Note, but is not including orders that don't have delivery notes.
select t0.docnum SalesOrder, t1.itemcode, t2.docnum DelivNoteNum, t3.baseline inv1base, t1.linenum rdr1line, t3.linenum dln1line
from ordr t0 inner join rdr1 t1 on t1.docentry = t0.docentry
right outer join odln t2 on t2.docentry = t1.trgetentry
right outer join dln1 t3 on t3.docentry = t2.docentry and t3.baseline = t1.linenum and t3.ItemCode = t1.ItemCode
where t0.CANCELED = 'N' and t2.canceled = 'N';
Expected results should be the same number of rows in each table. Actual results are only ordered with delivery notes.
Use left join, not right join. If you want all orders then start with that table. Filters on subsequent tables should go into the on clause:
select t0.docnum SalesOrder, t1.itemcode, t2.docnum DelivNoteNum,
t3.baseline inv1base, t1.linenum rdr1line, t3.linenum dln1line
from ordr t0 left join
rdr1 t1
on t1.docentry = t0.docentry left join
odln t2
on t2.docentry = t1.trgetentry and t2.canceled = 'N' left join
dln1 t3
on t3.docentry = t2.docentry and
t3.baseline = t1.linenum and
t3.ItemCode = t1.ItemCode
where t0.CANCELED = 'N';

How to replace an OR statement from a join in sql server

I have the following query that uses an or statement on a join, so basically if one condition on the join isn't met it must check the next condition. The problem is that with the OR statement it takes really long to run but when I remove one of the OR conditions it runs instantly. is there a better way to do this with both conditions without using the OR statement so it would speed up the query
select t5.TransactionNumber
,t4.ID
,t3.[Entry] AS Amount
,t2.Address AS AddressDetail
,t1.PhoneNumber AS ContactNumber
FROM Table1 t1 (NOLOCK)
JOIN Table2 t2 (NOLOCK) ON t2.FicaID = t1.FicaId
inner join Table3 t3 (NOLOCK) ON (t3.ID = t2.ID AND t3.Code = t2.Code) or (t3.TypeID = t2.TypeID) //on this join i have an or statement if one condition isnt met it must check the next condition
LEFT JOIN Table4 t4 (NOLOCK) ON t4.Result = t3.Result
LEFT JOIN Table5 t5 (NOLOCK) ON t5.AccNum = t3.AccNum
where t1.date>'2018-09-01' and t1.date<'2018-09-30'
By the rule of distributivity in logic,
P OR (Q AND R) can be written as
(P OR Q) AND (P OR R).. maybe that helps?
You could try by using left join and COALESCE function
select t5.TransactionNumber
,t4.ID
,COALESCE(t3.[Entry],t33.[Entry]) AS Amount
,t2.Address AS AddressDetail
,t1.PhoneNumber AS ContactNumber
FROM Table1 t1 (NOLOCK)
JOIN Table2 t2 (NOLOCK) ON t2.FicaID = t1.FicaId
left join Table3 t3 (NOLOCK) ON (t3.ID = t2.ID AND t3.Code = t2.Code)
left join Table3 t33 (t33.TypeID = t2.TypeID) //I moved it to left join
LEFT JOIN Table4 t4 (NOLOCK) ON t4.Result = t3.Result
LEFT JOIN Table5 t5 (NOLOCK) ON t5.AccNum = t3.AccNum
where t1.date>'2018-09-01' and t1.date<'2018-09-30'
You can try below query :
select * from
(
select t5.TransactionNumber
,t4.ID
,t3.[Entry] AS Amount
,t2.Address AS AddressDetail
,t1.PhoneNumber AS ContactNumber
FROM Table1 t1 (NOLOCK)
JOIN Table2 t2 (NOLOCK) ON t2.FicaID = t1.FicaId
inner join Table3 t3 (NOLOCK) ON (t3.ID = t2.ID AND t3.Code = t2.Code)
)A
join Table3 t3 (NOLOCK) ON (A.TypeID = t3.TypeID)
LEFT JOIN Table4 t4 (NOLOCK) ON t4.Result = t3.Result
LEFT JOIN Table5 t5 (NOLOCK) ON t5.AccNum = t3.AccNum
where t1.date>'2018-09-01' and t1.date<'2018-09-30'

Column invalid or group by in my query

I am working on a project in which I have to display the products and quantities.
This is my query:
select DATEDIFF(month,T3.startdate,T3.enddate) warranty_duration,
T2.ItemCode,T2.Quantity,T2.SerialNum,T4.ItemName,T2.SerialNum as
InternalSN,T3.ContractID,T3.issend,
T3.StartDate,T3.EndDate,T3.Remarks1 from ORDR T1
inner join RDR1 T2 on T1.DocEntry=T2.DocEntry
inner join OCTR T3 on T1.CardCode=T3.CstmrCode
inner JOIN OITM T4 ON T2.ItemCode=T4.ItemCode
WHERE (DATEDIFF(day,getdate(),T3.enddate)<=7 and
DATEDIFF(day,getdate(),T3.enddate)>=0)
and T3.isSend=0
and T4.SWW in ('PSG','IPG-H','ESSN-N','ESSN-ISS','ESSN-HPN','ESSN-
BCS','EABMS')
and t3.contractID = 23890
My Query shows result like this:
I want to show like this:
select DATEDIFF(month,T3.startdate,T3.enddate) warranty_duration,
T2.ItemCode,T2.Quantity,T2.SerialNum,T4.ItemName,T2.SerialNum as
InternalSN,T3.ContractID,T3.issend,
T3.StartDate,T3.EndDate,T3.Remarks1 from ORDR T1
inner join RDR1 T2 on T1.DocEntry=T2.DocEntry
inner join OCTR T3 on T1.CardCode=T3.CstmrCode
inner JOIN OITM T4 ON T2.ItemCode=T4.ItemCode
WHERE (DATEDIFF(day,getdate(),T3.enddate)<=7 and
DATEDIFF(day,getdate(),T3.enddate)>=0)
and T3.isSend=0
and T4.SWW in ('PSG','IPG-H','ESSN-N','ESSN-ISS','ESSN-HPN','ESSN-
BCS','EABMS')
and t3.contractID = 23890
GROUPBY T2.ItemCode
GROUP BY productName
(change bolded value to your own in DB) should do the trick.

How to categorize names in SQL query?

I have a query written below. there are the account names. they are giving me all database records. but i want the categories. for example if there are account name like 'salaries' then they should come under the salary title. if they are related to the 'expenses' then it should come under the expenses title. Please check out the below query
SELECT T1.[FormatCode], T1.[AcctCode], T1.[AcctName], T4.[Name] ,T2.[Name],
T0.[DebLTotal], T0.[DebRLTotal], T3.[Debit], T3.[RefDate]
FROM OBGT T0
INNER JOIN OACT T1 ON T0.[AcctCode] = T1.[AcctCode]
INNER JOIN OBGS T2 ON T0.[Instance] = T2.[AbsId]
INNER JOIN JDT1 T3 ON T1.[AcctCode] = T3.[Account]
INNER JOIN OASC T4 ON T1.[Project] = T4.[Code]
I want the categories according to the account code. for example if code is 51 then it is 'salaries' and all. Please expert help me.I am struggling with this thing for so long.
SELECT T1.[FormatCode], ( case when T1.[AcctCode]=51 then 'salaries' when T1.[AcctCode]=52 then 'dfds' end) as AcctName, T4.[Name] ,T2.[Name],T0.[DebLTotal], T0.[DebRLTotal], T3.[Debit], T3.[RefDate] FROM
OBGT T0 INNER JOIN OACT T1 ON T0.[AcctCode]=T1.[AcctCode] INNER JOIN OBGS T2 ON T0.[Instance] = T2.[AbsId] INNER JOIN JDT1 T3 ON T1.[AcctCode] = T3.[Account] INNER JOIN OASC T4 ON T1.[Project]=T4.[Code]