Weird calculation - mysql

Here are my two tables
users
------------------------
id username name surname
2 Foo f b
4 Bar b f
orders
---------------------
id user_id price qty
1 2 3.2 1
2 4 6 4
etc ...
And here is how my query looks like
SELECT
u.name,
u.surname,
COUNT(r.user_id) as total,
SUM(r.price) as total_price,
FROM orders r
LEFT JOIN users u on u.id = r.user_id
WHERE order_id = 4
GROUP BY user_id
Thus I get total of money that user is spent.
The problem is that the calculation is wrong because the user can be bought more than one item of product.
I can't figure out how to do so calculation to include and quanity.

You can try to multiply and sum, like :-
sum(r.price * r.qty) as total_price

Related

Getting percentage of total in SQL with two joins

So I'm trying to do something that I think should be fairly simple with SQL. But I'm having a hard time figuring it out. Here is the format of my data:
One table with user information, let's call it User:
ID name_user Drive_Type
1 Tim Stick shift
2 Jim Automatic
3 Bob Automatic
4 Lisa Stick shift
Then I have one table used for the join, let's call it Join_bridge:
user_ID car_has_ID
1 12
2 13
3 14
4 14
And one table with car information, let's call it Car:
car_ID name
12 Honda
13 Toyota
14 Ford
Then what I want is something that looks like this with the total number of Ford's that are stick shift and the percentage
name Total percentage
Ford 1 25%
I have tried the following, which gets the total right, but not the percentage:
select Drive_Type,
name,
count(Drive_Type) as Total,
(count(Drive_Type) / (select count(*)
from User
join Join_bridge
on User.ID = user_ID
join Car
on Car.car_ID = Join_bridge.car_has_ID
) * 100.0 as Percent
from User
join Join_bridge
on User.ID = Join_bridge.user_ID
join Car
on Car.car_ID = Join_bridge.car_has_ID
where name = 'Ford' and Drive_Type = "Automatic"
;
What am I missing? Thanks.
See this SQL Fiddle with the query - the trick is to SUM over CASE that returns 1 for rows you look for and 0 for the rest in order to calculate "Total" at the same time you can also count all rows to calculate percentage.
Here's the SQL query:
SELECT
'Ford' name,
SUM(a.ford_with_stack_flag) Total,
100.0 * SUM(a.ford_with_stack_flag) / COUNT(*) percentage
FROM (
SELECT
Car.name,
(CASE WHEN User.Drive_Type = 'Stick Shift' and Car.name = 'Ford' THEN 1 ELSE 0 END) ford_with_stack_flag
FROM User
JOIN Join_bridge on User.ID = Join_bridge.user_ID
JOIN Car ON Car.car_ID = Join_bridge.car_has_ID
) a
Compute percent and join to Car. Window functions are supported in MySql 8.0
select c.car_ID, c.name, p.cnt, p.Percent
from car c
join (
select car_has_ID, u.Drive_Type,
count(*) cnt,
count(*) / count(count(*)) over() Percent
from Join_bridge b
join user u on u.ID = b.user_ID
group by b.car_has_ID, u.Drive_Type
) p on p.car_has_ID = c.car_ID
where c.name = 'Ford' and p.Drive_Type='Stick shift';
db<>fiddle

SQL query to return items with count sale_id = 4

I have 3 tables:
user: user_id | user_name
Sale: sale_id(pk) | user_id(fk) | sale_amount
item: item_id(pk) | sale_id(fk)
The sale_id is generated everytime a user purchases from the item table.
I wish to generate an output that will written me user_id, sale_id and count(item_id) i.e, total items purchased by a user in separate transaction where count(sale_id) in item table =4.
I tried using this but it does not work:
select s.user_id,s.id, count(i.item_id)
from sale s join item i
on s.id = i.sale_id
group by s.use_id, i.sale_id
having count(i.sale_id) = 4
;
If a user_id 1 as 2 different transactions where in first transaction(sale_id = 3) he buys 2 items and in second transaction (sale_id = 13) he purchases 4 items which means in the item table each four items purchased will have same sale_id. So, I want to see the output where users have purchased 4 items in one transaction.
output:
s.user_id | i.sale_id | count(i.item_id)
1 13 4
you have aggregation with respect to s.user_id,s.id however you are grouping by s.user_id, i.sale_id. This typically causes error because your query is malformed.
furthermore if you put i.sale_id into group by and try to use having with count(i.sale_id) = 4 this never returns results. because count(i.sale_id) will always be either 0 or 1 when you group by with sale_id

Mysql trigger that multiplies two values from different tables, totalizes by groups and adds values to another column

I've been going around this for a while and there isno way I can figure it out. Let's say I have these three tables:
Users
Name | Basket value
-------+---------------
John | ???
-------+---------------
Pierre | ???
Items
User | Item | Amount
-----------+------------+------------
John | Pears | 2
-----------+------------+------------
Pierre | Pears | 1
-----------+------------+------------
Pierre | Apples | 3
Market_ prices
Item | Price
------------+---------------
Pears | 2.35
------------+---------------
Apples | 2.56
Basket value is needed. So for each row in ITEMS it must multiply its AMOUNT by MARKET_PRICES[PRICE] and sum all the results grouped by USER and place this result in USERS[total items value]. But how could the syntax be elaborated to take this to practice?
Many thanks in advance for the help.
One approach is to join the relevant tables:
SELECT u.name, SUM(i.amount*m.price)
FROM users u
JOIN items i ON u.name = i.user
JOIN market_prices m ON i.item = m.item
GROUP BY u.name;
(SQLfiddle of this is at: http://sqlfiddle.com/#!9/ec224/6 - I added a few other rows to the tables to test more complexity, so the totals aren't what you'd get from your example. Specifically, I added Bananas 3.75 to the Market_prices table and John Apples 3 and Pierre Bananas 5 to the Items table.)
The goal here is to link the information in all three tables through shared fields (via the JOIN), while also GROUPing and creating a SUM of the calculated costs as a product of market price and number of items.
---- edited based on comments ----
To do this as an update, you could try:
UPDATE users
SET basket_value = (SELECT basket FROM
(SELECT name, SUM(i.amount*m.price) AS basket
FROM users u JOIN items i ON u.name = i.username
JOIN market_prices m ON i.item = m.item
GROUP BY u.name) q1 WHERE q1.name = users.name);
I have a feeling there is a more elegant solution, but this works. Modified SQLFiddle is: http://sqlfiddle.com/#!9/56245a/1
SELECT User, SUM(rev) AS basket_price
FROM
(
SELECT a.User AS User, a.Amount*b.Price AS rev
FROM Items a
LEFT JOIN
Market_Prices b
ON a.Item = b.Item
) a1
GROUP BY User

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.

Joining over three table with sum() subquery

I'm having trouble getting a query to work where data is pulled from two tables, with a 3rd table in the middle. Let me show you what I mean.
*Table companies*
id int PK
name text
*Table projects*
id int PK
company_id int FK
project_name text
*Table hours_worked*
id int pk
user_id int FK
project_id int FK
hours float
date_worked datetime
*Table users*
id int PK
user_name text
Basically, what I need is a query that pulls the total amount of hours worked per company based on a user ID.
Note that the table_hours worked can have multiple submissions per day per project. For example, a few rows might look like
id project_id user_id hours date_worked
1 1 1 2 20-08-2012
2 1 1 1.5 20-08-2012
3 2 1 3 21-08-2012
4 2 2 12 22-08-2012
My desired result would be a query that returns something like this:
company_name total_hours
Bobs Kitchens 25
Mikes Bikes 67
Which returns the total number of hours worked per company (not project) for say, a user with the user ID of 1.
Here is the following query I've tried with no avail:
SELECT DISTINCT companies.name as company_name,
companies.id as company_id,
(
SELECT SUM(hours_worked.hours) FROM hours_worked
WHERE projects.id = hours_worked.project_id
AND projects.company_id = company_id
) as total_hours
FROM hoursworked, companies, projects
WHERE projects.company_id = company_id
AND projects.company_id = projects.company_id
AND hours_worked.user_id = 1
GROUP BY companies.id
This is giving me an odd result where a really weird number appears to be displaying for every total_hours field. 75 is not the correct total hours for any company!
company_name total_hours
Mikes Kitchen 75
Charlies Bikes 75
..... 75
Any help would be greatly appreciated!
Try this:
SELECT c.name company_name, u.user_name, SUM(h.hours) total_hours
FROM projects p
INNER JOIN companies c ON p.company_id = c.id
INNER JOIN hours_worked h ON p.id = h.project_id
INNER JOIN users u ON h.user_id = u.id
GROUP BY c.id, u.id
I was such a fool..it was actually a lot easier than I expected. Hurray for over thinking.
The query I've used is:
SELECT SUM(hours_worked.hours) as 'total_hours',
companies.name
FROM companies, hours_worked, projects
WHERE companies.id = projects.company_id
AND hours_worked.project_id = projects.id
AND hours_worked.uid = 1
GROUP BY companies.id ORDER BY companies.name DESC