Sql - Getting Sum on the join table - sql

I just want to get the result which displays the reference which is not tallied in sum of table2. when i run my query below it will give me an wrong sum which it gets doubled even if group by cusid ,refno.
Table 1
RefNo
CusID
TotalAmount
1
1001
50
2
1001
30
3
1002
40
Table 2
RefNo
CusID
Particular
Amount
1
1001
Paper
30
1
1001
Pencil
30
2
1001
Ball
15
2
1001
Rubber
20
3
1002
Laptop
50
select * from Table1 a
INNER JOIN (Select CusID,RefNo, SUM(Amount) as CorrectTotal from Table2 group by
CusID,RefNo,
)b
ON b.CusID= a.CusID AND b.RefNo= a.RefNo
where a.TotalAmount != CorrectTotal
Expected Result

If you do it with FULL JOIN and with GROUP BY, you will also get rows where there is no record in the other table.
SELECT COALESCE(a.RefNo, b.RefNo) AS RefNo
, COALESCE(a.CusID, b.CusID) AS CusID
, a.TotalAmount
, SUM(b.Amount) AS CorrectTotal
FROM table1 a
FULL JOIN table2 b ON a.RefNo = b.RefNo
AND a.CusID = b.CusID
GROUP BY COALESCE(a.RefNo, b.RefNo)
, COALESCE(a.CusID, b.CusID)
, a.TotalAmount
ORDER BY 1, 2
Output
RefNo
CusID
TotalAmount
CorrectTotal
1
1001
50
60
2
1001
30
35
3
1002
40
50
8
888
88
(null)
9
999
(null)
99
See running demo on SQL Fiddle.

The other answer will work, but if you don't want to mess with a GROUP BY on the whole query you can also use an APPLY to do this:
SELECT a.*, c.CorrectAmount
FROM Table1 a
OUTER APPLY (
SELECT SUM(Amount) AS CorrectAmount
FROM Table2 b
WHERE b.CusID = a.CusID AND b.RefNo = a.RefNo
) c
WHERE a.TotalAmount <> c.CorrectAmount

Related

Complex SQL Query in JOIN

Tables
TRANSACTIONS
SUPP_ID | PAYMENT
----------+----------
1001 200
1002 100
1005 250
MASTER_SUPPLIERS
SUPP_ID | AREA
----------+----------
1001 ABC
1002 XYZ
1003 TYU
1004 MNO
1005 PQR
Intention:
Find those count of suppliers area wise where no payment (NO_TRANS_CNT) has been received
SELECT AREA, COUNT(*) AS NO_TRANS_CNT FROM MASTER_SUPPLIERS
WHERE AREA NOT IN (SELECT DISTINCT(AREA) FROM TRANSACTIONS)
GROUP BY AREA
AREA | NO_TRANS_CNT
----------+--------------
TYU 1
MNO 1
Want to ask: Now, I also want to add the column TOTAL_SUPPLIERS in this area
AREA | TOTAL SUPPLIERS | NO_TRANS_CNT
----------+--------------------+----------------
ABC 1 0
XYZ 1 0
TYU 1 1
MNO 1 1
PQR 1 0
I think it can be achieved using JOINs, but I am not able to get how ?
Try this:
SELECT
M.AREA
, COUNT(1) TOTAL_SUPPLIERS
, COUNT(CASE WHEN T.SUPP_ID IS NULL THEN 1 END) NO_TRANS_CNT
FROM MASTER_SUPPLIERS M
LEFT JOIN TRANSACTIONS T ON T.SUPP_ID = M.SUPP_ID
GROUP BY M.AREA;
Something like
select M.AREA, COUNT(*) as TOTAL_SUPPLIERS, COUNT(T.PAYMENT) as NO_TRANS_CNT
from MASTER_SUPPLIERS M left join TRANSACTIONS T
on M.SUPP_ID = T.SUPP_ID
group by M.AREA;
could work.
Note that the COUNT(T.PAYMENT) only counts those where the PAYMENT is not NULL.
Use a left join, but start with suppliers:
select ms.area, count(*) as num_suppliers, count(t.supp_id) as num_transactions
from master_suppliers ms left join
transactions t
on t.supp_id = m.supp_id
group by ms.area;
The left join keeps everything in the first table -- which is what you want, along with matching rows from the second.
When you count the number of transactions, the argument to count() should either be a column used in the on clause or the primary key.

Oralce SQL nested or inner join when you need to compare the same table but different rows with unique ID values

I'm having a trouble writing a query in ORACLE. I have a Table that contains values. for example:
ID quantity partID
123 50 10
100 20 10
100 30 11
123 null 8
456 null 100
789 25 123
456 50 9
I want to get all rows that has same ID but quantities to be 50 and null (exact same pairs of 50 and null only). for the given example I would like to get:
ID quantity partID
123 50 10
123 null 8
456 50 9
456 null 100
I tried inner join but it doesn't provide the exact output as expected.
You may try :
select ID, quantity, partID
from tab
where ID in
(
select ID
from tab
where nvl(quantity,50)=50
group by ID
having count(distinct nvl(quantity,0) )>1
);
ID QUANTITY PARTID
123 50 10
123 (null) 8
456 (null) 100
456 50 9
SQL Fiddle Demo
P.S. you may get the same results by commenting out having count(ID)=2 also but for those cases there may not exist one of 50 or null for values of quantity.
You can use exists:
select t.*
from t
where (t.quantity = 50 and
exists (select 1 from t t2 where t2.id = t.id and t2.partid = t.partid and t2.value is null)
) or
(t.quantity is null and
exists (select 1 from t t2 where t2.id = t.id and t2.partid = t.partid and t2.value = 50)
) ;

SQL query to find top 2 customers done max amount of transaction( oracle db) [duplicate]

This question already has answers here:
How do I do top 1 in Oracle? [duplicate]
(9 answers)
Closed 5 years ago.
I want to get TOP 2 customers done maximum amount transaction from below the table.I am working on oracle db.
my table transactions:
tranID PROD_ID QTY PRICE CID
1 100 5 10000 1000
2 103 16 5000 1001
3 102 8 5000 1003
4 200 10 9000 1002
5 204 8 9000 1002
6 207 4 8000 1002
CUSTOMERS
CID CNAME
1001 X
1002 Y
1003 Z
If Oracle 12c , you can use this.
SELECT a.CID, b.CNAME, SUM (a.QTY * a.PRICE) amount
FROM transactions a JOIN CUSTOMERS b ON a.CID = b.CID
GROUP BY a.CID, b.CNAME
ORDER BY amount DESC
FETCH FIRST 2 ROWS ONLY
You could use a summ group by and a join and last filter for rownum
select a.CID, b.CNAME, sum(a.QTY*a.PRICE) amount
from transactions a
INNER JOIN CUSTOMERS b on a.CID = b.CID
WHERE ROWNUM < 3
GROUP BY a.CID, b.CNAME
ORDER BY amount
This can be done using the following query. First, you compute sums, then you order it and then you select the first two rows.
SELECT t.*
FROM
(
SELECT t.CID, c.name, sum(t.PRICE * t.qty) tsum
FROM transaction t
JOIN customer c ON t.CID = c.CID
GROUP BY t.CID , c.name
ORDER BY tsum DESC
) t
WHERE rownum < 3

How to Join two table using where and sum statement

Dear All I have below two table
Table1
RecdId RecdNo
1 A/1
2 A/2
3 A/3
Table2
RecdId RecdAmt1 RecdAmt2 RecdAmt3
1 100 10 5
1 150 20 10
1 200 30 15
2 500 5 50
2 400 10 60
3 100 5
I want solution that how to join above two table with sum of Table1.RecdId = Tabble2.RecdId
Below result I require
RecdId RecdNo TotRecdAmt1 TotRecdAmt2 TotRecdAmt3
1 A/1 450 60 30
2 A/2 900 15 110
3 A/3 100 5
Thanking You,
You can inner join two tables and use a group by clause to calculate sum for each combination of RecdId and RecdNo:
select t1.RecdId
, t1.RecdNo
, sum(t2.RecdAmt1) as TotRecdAmt1
, sum(t2.RecdAmt2) as TotRecdAmt2
, sum(t2.RecdAmt3) as TotRecdAmt3
from tbl1 t1
join tbl2 t2 on t1.RecdId = t2.RecdId
group by t1.RecdId
, t1.RecdNo
SQLFiddle
SELECT T1.RECDID, T1.RECDNO, TotRecdAmt1, TotRecdAmt2, TotRecdAmt3
FROM TABLE1 T1, (SELECT RECdID, SUM(RecdAmt1) TotRecdAmt1, SUM(RecdAmt2) TotRecdAmt2,
SUM(RecdAmt3) TotRecdAmt3 FROM TABLE2 GROUP BY RECdID) T2
WHERE T1.RECdID = T2.RECDID;
SELECT Table1.RecdId,RecdNo,SUM(RecdAmt1) AS TotRecdAmt1,
SUM(RecdAmt2) AS TotRecdAmt2,
SUM(RecdAmt3) AS TotRecdAmt3
FROM Table1,Table2
WHERE Table1.RecdId=Table2.RecdId
GROUP BY Table1.RecdId,RecdNo

Last Record Of Each Group Using Multiple Joins In Sql Server

I Have 3 tables Customer, Bank and BankTransaction.
On My View I want to display each customer with their Balance in the bank account.
Here is my tables
Customer
Id Name
---------
1 John
2 Jack
Bank
Id CustomerId BankName
----------------------------------
1 1 HSBC
2 2 HSBC
BankTransaction
Id BankID MoneyIn MoneyOut Balance
---------------------------------------------
1 1 1000 0 1000
2 1 0 500 500
3 2 2000 0 2000
4 2 2000 0 4000
5 2 1000 0 5000
Now I want to Display following data view query
John 500
Jack 5000
Last Balance of each customer
Try this
SELECT A.Name,
Sum(C.MoneyIN) - Sum(C.MoneyOut) AS Balance
FROM #Customer A
JOIN #Bank B ON A.Id = B.id
JOIN #BankTransaction C ON B.Id = C.BankID
GROUP BY A.Name
Using Window function you can get the result. Try this.
;WITH cte
AS (SELECT Row_number() OVER (partition BY b.id ORDER BY a.id DESC) rn,
c.Name,
a.balance
FROM BankTransaction a
JOIN bank b ON a.BankID = b.Id
JOIN Customer c ON c.Id = b.CustomerId)
SELECT name, balance
FROM cte
WHERE rn = 1