Reputation: 53
The question requires us to join multiple tables and show the balance each account has based off of orders and payments already made.
Due to MS-Access specific syntax, you're unable to join two queries in a from clause using aliases. I've tried using the UNION feature but that also doesn't seem to be working. Below you can see the two queries that I've been trying to join together.
Query 1
SELECT c.clientname, SUM(p.payment) AS Total_Paid
FROM clients c INNER JOIN payments p ON c.clientnumber = p.clientnumber
GROUP BY c.clientname
Result
[Client Name] [Total_Paid]
Client A 1000
Client B 1500
Client C 2000
Query 2
SELECT c.clientname, SUM(i.orderamount * i.itemprice) AS Total_Owed
FROM (clients c INNER JOIN orders o ON c.clientnumber = o.clientnumber)
INNER JOIN orderinfo i ON i.ordernum = o.ordernum
GROUP BY c.clientname
Result
[Client Name] [Total_Owed]
Client A 1000
Client B 2500
Client C 3000
What I'd like to have my result be is a table that is the result of subtracting Total_Paid from Total Owed, while only using a single query to do so.
I've tried running this query as a starting point
(SELECT c1.clientname, SUM(p.payment) AS Total_Paid
FROM clients c1 INNER JOIN payments p ON c1.clientnumber = p.clientnumber
GROUP BY c1.clientname)
UNION
(SELECT c.clientname, SUM(i.orderamount * i.itemprice) AS Total_Owed
FROM (clients c INNER JOIN orders o ON c.clientnumber = o.clientnumber)
INNER JOIN orderinfo i ON i.ordernum = o.ordernum
GROUP BY c.clientname)
But the results I get are something like this
[Client Name] [Total_Paid]
Client A 1000
Client A 1000
Client B 1500
Client B 2500
Client C 2000
Client C 3000
Instead of
[Client Name] [Total_Owed][Total_Paid]
Client A 1000 1000
Client B 2500 1500
Client C 3000 2000
Finished result should look something like
[Client Name] [Balance]
Client A 0
Client B 1000
Client C 2000
Please let me know if any clarification is needed!
Upvotes: 0
Views: 96
Reputation: 1269513
I would write this as:
SELECT c.clientname, p.Total_Paid, o.Total_Owed
FROM (clients c LEFT JOIN
(SELECT p.clientnumber, SUM(p.payment) AS Total_Paid
FROM payments p
GROUP BY p.clientnumber
) as p
ON c.clientnumber = p.clientnumber
) LEFT JOIN
(SELECT o.clientnumber, SUM(oi.orderamount * oi.itemprice) AS Total_Owed
FROM orders o INNER JOIN
orderinfo oi
ON oi.ordernum = o.ordernum
GROUP BY o.clientnumber
) o
ON c.clientnumber = o.clientnumber;
Note: This returns all clients, even those with no payments or no orders. That appears to be the intend of your question.
Upvotes: 0
Reputation: 559
You have tables for clients
, payments
, orders
, and orderinfo
. It looks like the relationships are clients
JOINs to payments
and orders
on the client_number
and that orders
JOINs to orderinfo
in the order_number
. So you will need to aggregate the payments and orders together as you have above, but instead of using a UNION, you'll need to JOIN those two aggregated amounts as derived tables. This will allow you to subtract the amounts as opposed to stacking them vertically in the results. JOINs can add columns from related tables whereas UNIONs can stack similar structured results from different queries. Since the desired comparison is side by side you'd need to JOIN to operate on the calculated metrics as if they were a part of the same row but in different columns. I used a LEFT JOIN and started with orders
because I can imagine there exists a possibility for someone to order without having yet paid, and you would like to see that result still with their full balance due. An INNER JOIN would only yield results where a client has both an order and a payment. Access does not support COALESCE() or CASE expressions, so IIF() was used to get rid of the the cases without payments (which would be null and therefore cannot be used in subtraction).
SELECT
tot_owed.clientname
, tot_owed.Total_Owed
- IIF(tot_paid.Total_Paid IS NULL, 0, tot_paid.Total_Paid) AS Balance
FROM (
SELECT
c.clientname
, c.clientnumber
, SUM(i.orderamount * i.itemprice) AS Total_Owed
FROM
clients c
INNER JOIN
orders o ON c.clientnumber = o.clientnumber
INNER JOIN
orderinfo i ON i.ordernum = o.ordernum
GROUP BY
c.clientname
, c.clientnumber
) tot_owed
LEFT JOIN (
SELECT
c.clientname
, c.clientnumber
, SUM(p.payment) AS Total_Paid
FROM
clients c
INNER JOIN
payments p ON c.clientnumber = p.clientnumber
GROUP BY
c.clientname
, c.clientnumber
) tot_paid ON tot_owed.clientnumber = tot_paid.clientnumber
Upvotes: 1