Union Select two queries subtract from particular data - ms-access

I need to build a query which performs subtraction on basis of client name here is my query I built for getting data
SELECT invoice.client_name, (Sum(invoice.freight_rate)+Sum(invoice.total_basic_amount)+Sum(invoice.delivery_rate))
FROM invoice GROUP BY invoice.client_name
UNION SELECT client_name,(Sum(payments.payment_received))
FROM payments GROUP BY client_name
And here is what I get as an output
client_name | Expr1001
John | 2500
John | 3630
MAc | 12000
MAc | 15300
What I need is
client_name | Expr1001
John | 1130
MAc | 3300
Which is simple subtraction of both query.
I already asked this question before and I got some good responses but they aren't working and now nobody replies to it. Here is what I got from them.
SELECT invoice.client_name, (Sum(invoice.freight_rate)+Sum(invoice.total_basic_amount)+Sum(invoice.delivery_rate)-Sum(payments.payment_received)) AS Expr1
FROM invoice, payments
WHERE (([invoice].[client_name]=[payments].[client_name]))
GROUP BY invoice.client_name;
This query returns some very strange output which is
client_name | Expr1001
John | 2260
MAc | 18600
I'm Attaching the db file here is the link.
https://drive.google.com/file/d/1dbxHzXDbfe8l1ZDN9ZxZo7Rs1UImhV8r/view?usp=share_link

You need subqueries:
Select
Charges.client_name,
TotalCharges-TotalPayments As Total
From
(Select
invoice.client_name,
Sum(CCur([invoice].[freight_rate]))+Sum(CCur([invoice].[total_basic_amount]))+Sum(CCur([invoice].[delivery_rate])) As TotalCharges
From
invoice
Group By
invoice.client_name) As Charges
Inner Join
(Select
payments.client_name,
Sum(CCur([payment_received])) As TotalPayments
From
payments
Group By
payments.client_name) As Payments
On Charges.client_name = Payments.client_name
and you should not store amount as text ...

There are multiple invoice and payment records for each client. This means must aggregate each table's data then join those datasets.
SELECT I.client_name, amt - pmt AS Total
FROM (SELECT client_name, Sum(total_basic_amount) AS amt FROM invoice GROUP BY client_name) AS I
LEFT JOIN (SELECT client_name, Sum(payment_received) AS pmt FROM payments GROUP BY client_name) AS P
ON I.client_name = P.client_name;
Or this version:
SELECT invoice.client_name, Sum(total_basic_amount)-Max(pmt) AS Total
FROM Invoice LEFT JOIN (SELECT client_name, Sum(payment_received) AS pmt FROM Payments GROUP BY client_name) AS P
ON invoice.client_name = P.client_name
GROUP BY invoice.client_name;

Related

SQL: join 2 tables based on column value and select row values where grouped column value is max

Ive got this query and I want to get all names from those clients that have the highest price of a day.
If multiple clients exist having the same max price, they shall be selected too.
I managed to get the customers with max price grouped by date but I dont think it gives me both customers if they have the same max value on the same day.
The names should be distinct.
The output needs to be as follows:
| Name (asc) |
------------------
| customer name |
| customer name |
| ...... |
The Orders table looks as follows:
|Client|Price|Orderdate |
------------------------
|1 |100.0|2010.01.10|
|... |... | ..... |
and the Client table:
|Client_NR|Name |
-----------------------
|1 |customer#001|
|2 |customer#002|
select distinct k1.NAME from Orders a LEFT JOIN Order b on a.Orderdate = b.Orderdate
JOIN Client k1 on k1.Client_NR = a.Client
where a.Price IN
(SELECT MAX(a.Price) from Order a group by Orderdate)
order by NAME asc
I presume my error lies within the Join Client line but I just cant figure it out.
Ive tried to use a.price = b.price in the first join but the test would fail.
Any advise is highly appreciated.
WITH cte AS ( SELECT Client.Name,
RANK() OVER (PARTITION BY Orders.Orderdate
ORDER BY Orders.Price DESC) rnk
FROM Client
JOIN Orders ON Client.Client_NR = Orders.Client )
SELECT Name
FROM cte
WHERE rnk = 1
ORDER BY Name

aggregate tables with AVG

I am new to SQL.
I checked "another solutionSQL JOIN two tables with AVG" posted in StackOverflow. And I don't get the meaning with this line in that article:AVG(score.score * 1.0) Besides, the alternative solution below doesn't work at all:
SELECT songs.id, songs.song, songs.artist,
(SELECT AVG(Score) FROM score WHERE score.id = songs.id) AS AvgScore)
FROM songs
Here are my tables:
[employees]
Dep ID | SALARY
1 | 500
2 | 200
1 | 300
2 | 1000
2 | 400
3 | 200
3 | 300
[departments]
Dept ID Dep| Dept Name
1 | Volcano
2 | ShootingStar
3 | Tsunami
In the end, I want to create a list looks like:
Dept Name | Average Salary
Volcano | $$$
ShootingStar| $$
Tsunami | $$$$
I tried various ways and hunting hints in stackoverflow for sub queries/inner join features but still can't get it.
Based on the solution in the previous link SQL JOIN two tables with AVG, this code works:
-- mapping DEPT ID with NAME + average salary by DEPT --
select EMPLOYEES.DEP_ID, DEPARTMENTS.DEP_NAME, AVG(EMPLOYEES.SALARY) as AVG_S
from EMPLOYEES
LEFT JOIN DEPARTMENTS
ON EMPLOYEES.DEP_ID = DEPARTMENTS.DEPT_ID_DEP
group by DEP_ID, DEP_NAME;
However, I want to understand the reason WHY my original one doesn't work?
select E.DEP_ID, D.DEP_NAME, (select AVG(SALARY) from EMPLOYEES group by DEP_ID) as AVG_S
from EMPLOYEES E, DEPARTMENTS D
where E.DEP_ID = D.DEPT_ID_DEP
group by DEP_ID, DEP_NAME;
Please help!
Thank you very much.
The query you wanted to write:
select
e.dep_id,
d.dep_name,
(select avg(salary) from employees e where e.dep_id = d.dept_id_dep) as avg_s
from departments d;
The logic of the query is to select from departments only, then use a correlated subquery to compute the average salaries of employees of the department. This avois aggregating in the outer query.
Your query fails in the following regards:
table employees is in the from clause of the outer query
the outer query does group by
the subquery is not corelated on the department

mysql group by query (very close)

I have 3 tables (simplified):
orders (orderid, date)
orderlines (lineid, orderid, userid)
users (userid, name)
I would like a list of numbers of orders per user grouped by year and month orders by username. The reason why order lines have the user id is that an order line can be changed by another user. The following gives me a list of numbers of order lines, but it needs to count the orders only:
SELECT
users.name,
COUNT(orders.orderid) AS number,
MONTH(orders.date) AS month,
YEAR(orders.date) AS year
FROM orders
INNER JOIN orderlines ON orders.orderid = orderlines.orderid
INNER JOIN users ON orderlines.userid = users.userid
GROUP BY orderlines.userid, YEAR(order.date), MONTH(order.date)
ORDER BY users.name, orders.date
I'm feeling I'm very close...
Current output is:
name | number | month | year
----------------------------
jeff | 1000 | 1 | 2018
jeff | 1100 | 2 | 2018
Should be:
name | number | month | year
----------------------------
jeff | 100 | 1 | 2018
jeff | 110 | 2 | 2018
The number currently shown is the number of order lines, but I would like it to be the number of orders.
Try below: you need to use users.name in group by, also it should be in your order by clause as your question says it, another thing is as you want to know the count of order per user, so it should be count distinct orderid
SELECT users.name, COUNT(distinct orders.orderid), MONTH(orders.date), YEAR(orders.date)
FROM orders
INNER JOIN orderlines ON orders.orderid = orderlines.orderid
INNER JOIN users ON order lines.userid = users.userid
GROUP BY users.name, YEAR(order.date), MONTH(order.date)
ORDER BY users.name

Difference of sums from two different tables with grouping statement in MySql [duplicate]

This question already has answers here:
Join tables with SUM issue in MYSQL
(2 answers)
Closed 4 years ago.
I'm creating a portal with customers with sell/payment options, where all sells are in one table and all payments in another. For customer status table I need to get a sum of all payments per client and all sells per client plus difference between them.
Sample tables:
table clients
====================================
id client_name
====================================
1 School "Mike Jordan"
2 Car wash "Blah blah"
table purchasing
===================================
id client_id amount
===================================
1 1 1000
2 1 500
3 2 800
4 2 800
table payments
===================================
id client_id amount
1 1 300
2 2 200
3 2 200
I have tried with inner join and grouping but this is not getting sum properly, always larger one, like it is counting things I don't want (with no total, just trying to get sums:
select clients.`client_name `,
sum(purchasing.amount) as SOLD,
sum(payments.amount) as PAID
from clients
inner join payments on payments.client_id=clients.id
inner join purchasing on purchasing.client_id=clients.id
group by clients.id
where I got results different (all bigger).
client_name SOLD PAID
================================
School "Mike Jordan" 1500 600
Car wash "Blah blah" 3200 800
If I try to add grouping by payments.id and/or purchasing.id a got more than two results... I know that there is a grouping problem but I really have no idea where it is.
And I wanted to add new column which is just difference between SOLD and PAID, but server generates error with message that SOLD and PAID are not in a field list.
Any idea how to accomplish this with a single query?
You can try this. use UNION ALL to combine purchasing and payments table then join to clients.
Next step do SUM and group by
create table clients(
id int,
client_name varchar(50)
);
insert into clients values (1,'School "Mike Jordan"');
insert into clients values (2,'Car wash "Blah blah"');
create table purchasing(
id int,
client_id int,
amount int
);
insert into purchasing values (1,1,1000);
insert into purchasing values (2,1,500);
insert into purchasing values (3,2,800);
insert into purchasing values (4,2,800);
create table payments(
id int,
client_id int,
amount int
);
insert into payments values (1,1,300);
insert into payments values (2,2,200);
insert into payments values (3,2,200);
Query 1:
select c.client_name,
sum(SOLD) as SOLD,
sum(PAID) as PAID
from (
SELECT client_id,amount as SOLD,0 as PAID
FROM purchasing
UNION ALL
SELECT client_id,0,amount
FROM payments
)t1 INNER JOIN clients c on t1.client_id = c.id
group by c.client_name
Results:
| client_name | SOLD | PAID |
|----------------------|------|------|
| Car wash "Blah blah" | 1600 | 400 |
| School "Mike Jordan" | 1500 | 300 |
You need to summarize your tables before doing joins.
SELECT clients.`client_name`
,purchasing_sum.SOLD
,payments_sum.PAID
FROM clients
INNER JOIN (
SELECT client_id
,sum(amount) as PAID
FROM payments
GROUP BY client_id
) payments_sum ON payments_sum.client_id = clients.id
INNER JOIN (
SELECT client_id
,sum(amount) as SOLD
FROM purchasing
GROUP BY client_id
) purchasing_sum ON purchasing_sum.client_id = clients.id
GROUP BY clients.id

Sql query to get data diffrence of total in 2 tables

I have two tables:
booking - records the order detail
id | booking_amount
-------------------
1 | 150
2 | 500
3 | 400
payment - records the payment for order
id | booking_id | amount
------------------------
1 | 1 | 100
2 | 1 | 50
2 | 2 | 100
I want to find all bookings where the payments are not complete. With the above data, we expect the answer to be 2,3, because the sum of payments for booking_id=1 matches the corresponding booking_amount in the booking_table.
To answer your question, you have 2 things you need to think about :
you want the total amount in your table payment by every booking row
you want to join your booking_amount table with payment.
Part 1 is quite simple:
SELECT sum(amount) as TotalP, booking_id FROM payment GROUP BY booking_id
Just a basic query with a simple aggregate function...
For part 2, we want to join booking_amount and payment; the basic JOIN would be:
SELECT * FROM booking b
LEFT JOIN payment p ON b.id = p.booking_id
We do a LEFT JOIN because we may have some booking who are not in the payment table. For those bookings, you will get NULL value. We will use a COALESCE to replace the NULL values by 0.
The final query is this:
SELECT b.id, COALESCE(TotalP, 0), b.booking_amount
FROM
booking b
LEFT JOIN
(SELECT sum(amount) as TotalP, booking_id FROM payment GROUP BY booking_id) as T
ON b.id = T.booking_id
WHERE COALESCE(TotalP, 0) < b.booking_amount
You need to use a outer join to combine your two tables and look for your conditions. Also, you will need to use SUM(..) function to get the sum of the amount for each id in the payment table.
Please try this:
select b.id from booking b
left outer join -- cant be inner join because we lose id:3 in that case.
(
select booking_id, SUM(amount) as Total
from payment group by booking_id
) p on b.id = p.booking_id
where b.booking_amount > Coalesce(Total,0) --Coalesce is required for such values coming NULL, like id:3, they will be assigned as 0.