Skip to Main Content
  • Questions
  • Two SUM from different tables give weird result

Breadcrumb

XMAS_TREE

The AskTOM team is taking a break over the holiday season, so we're not taking questions or responding to comments, but we might still sneak in a few Office Hours sessions! Thanks for being a member of the AskTOM community.

Question and Answer

Connor McDonald

Thanks for the question.

Asked: December 06, 2024 - 10:03 am UTC

Last updated: December 11, 2024 - 6:08 am UTC

Version: Oracle 21c

Viewed 100+ times

You Asked

I have three tables. Clients, Invoices and Payments and I try to make a sum of invoiced amount and a sum of payments in the same script

If I run the sum of invoiced amount, all things are good, like below

select a.id, a.name,
sum(b.quantity*b.unitprice)
from clients a, invoices b
where a.id=b.client_id
group by a.id, a.name


ID NAME SUM(B.QUANTITY*B.UNITPRICE)
1 Client1 325
2 Client2 150
3 Client3 30


If I run a sum of payments the result is correct, like below


select a.id, a.name,
sum(c.amount)
from clients a, payments c
where a.id=c.client_id
group by a.id, a.name


ID NAME SUM(C.AMOUNT)
1 Client1 200
2 Client2 125
3 Client3 30

But if I try to make both SUM in a single select, the result is wrong and I don't know what I'm doing wrong

select a.id, a.name,
sum(b.quantity*b.unitprice),
sum(c.amount)
from clients a, invoices b, payments c
where a.id=b.client_id and a.id=c.client_id
group by a.id, a.name


ID NAME SUM(B.QUANTITY*B.UNITPRICE) SUM(C.AMOUNT)
1 Client1 650 400
2 Client2 300 250
3 Client3 30 30

and Connor said...

Without test data we can't really help much :-( but if I had to guess you have two one-to-many relationships, eg

For example, if you had a table called COLLEGE (1 row) and underneath there were two tables FULLTIME_STUDENTS (3 rows) and PARTTIME_STUDENTS (2 rows)

A join from COLLEGE to FULLTIME_STUDENTS , gives 3 rows
A join from COLLEGE to PARTTIME_STUDENTS , gives 2 rows

But a join with COLLEGE , PARTTIME_STUDENTS , FULLTIME_STUDENTS with no join criteria between the two student tables would return 6 rows (and thus break any SUM)



Rating

  (2 ratings)

We're not taking comments currently, so please try again later if you want to add a comment.

Comments

Trying SUM from two different table does not give correct result

Robert, December 09, 2024 - 4:52 am UTC

Hello,

The Clients table looks like this

ID NAME
1 Client1
2 Client2
3 Client3
4 Client4

The Invoices table looks like this

ID CLIENT_ID QUANTITY UNITPRICE
1 1 10 10
2 1 15 15
3 2 10 10
4 2 5 10
5 3 3 10

The Payments table:

ID CLIENT_ID AMOUNT
1 1 100
2 1 100
3 2 50
4 2 75
5 3 30


If I run the select statement below against Invoices:

select a.id, a.name,
sum(b.quantity*b.unitprice)
from clients a, invoices b
where a.id=b.client_id
group by a.id, a.name

the result is correct
ID NAME SUM(B.QUANTITY*B.UNITPRICE)
1 Client1 325
2 Client2 150
3 Client3 30

If I run the select statement below against Payments:

select a.id, a.name,
sum(c.amount)
from clients a, payments c
where a.id=c.client_id
group by a.id, a.name

the result is correct
ID NAME SUM(C.AMOUNT)
1 Client1 200
2 Client2 125
3 Client3 30

But if I want to have in a single select statement both SUM from Invoices and SUM from Payments, the select show incorrect data

select a.id, a.name,
sum(b.quantity*b.unitprice),
sum(c.amount)
from clients a, invoices b, payments c
where a.id=b.client_id and a.id=c.client_id
group by a.id, a.name

ID NAME SUM(B.QUANTITY*B.UNITPRICE) SUM(C.AMOUNT)
1 Client1 650 400
2 Client2 300 250
3 Client3 30 30


And I don't know why

For each Row

paul, December 09, 2024 - 2:06 pm UTC

Because the join clause (your where statement)
is saying
"For each row meeting this criteria, do the Select from above".
So it runs for all clients and their invoices AND all clients and their payments.

To see that, rerun your query without the group by. Just do the join and see how many rows you get back.

If what you are looking for is a table with a client and their SUM invoice amounts and SUM payment amounts you should do the SUM./ Group By FIRST and then you can join those.

--what you might be looking for
with ci as (
select 
   c.id clientid,
   c.name, 
   sum(i.quantity*i.unitprice) invoicedAmt
from 
  clients c, 
  invoices i
where c.id = i.clientid
    group by c.id,c.name
),
 cp as (
    select 
  c.id clientid,
  c.name,
  sum(p.payment) paidAmt
from 
  clients c left outer join payments p on c.id=p.clientid
group by c.id, c.name
)
select 
  c.id, 
  c.name,
  ci.invoicedAmt,
  cp.paidAmt
from 
    clients c
LEFT OUTER JOIN ci ON c.id=ci.clientid 
LEFT OUTER JOIN cp ON c.id=cp.clientid;


Gives

Result Set 6
ID NAME INVOICEDAMT PAIDAMT
1 client1 325                        305
2 client2 1300                1280
4 client4 100                         - 
3 client3 120                        110



NOTE: I shortpaid all the payments by 10$ so you can see the values from each tables.
NOTE: a,b,c are not great aliases. Try and use ones that clearly identify the source table (clients c, invoices i, payments p ...)
NOTE: used LEFT OUTER join because maybe a client has an invoice and no payment or no payments or invoices.

LiveSQL Link to see the different queries

https://livesql.oracle.com/ords/livesql/s/cpb02dav5l5wyjxbtll3sg290
Connor McDonald
December 11, 2024 - 6:08 am UTC

nice stuff