SUM, GROUP BY AND LEFT JOIN in query - mysql

I've two tables:
`orders`
order_id order_office_id order_invoice_id
1 1 1
2 2 2
3 2 2
4 2 3
5 1 4
`invoices`
inv_id inv_order_id inv_amount
1 1 500.00
2 0 320.00
3 3 740.00
4 4 160.00
With this query:
SELECT SUM(inv_amount) matrah, order_office_id
FROM `invoices`
LEFT JOIN orders ON order_invoice_id = inv_id OR inv_order_id = order_id
WHERE order_id IS NOT NULL
GROUP BY order_office_id
It is multiplying some amounts.
What I want to get sum of amounts by office:
office_id sum
1 660.00
2 1060.00
How to get proper amounts by single query?

This does what you want, I think
select sum(inv_amount) as matrah,
(select order_office_id from orders where order_invoice_id = inv_id limit 1) as office
from invoices
group by office;
I've removed the OR, because you were getting two office ids for one of the orders, so it was ambiguous. I've included a subquery to make sure that only one office is applied to each order.

This query may help you out:
SELECT SUM(i.inv_amount) matrah, o.order_office_id
FROM `invoices` AS i
LEFT JOIN `orders` AS o
ON o.order_invoice_id = i.inv_id
GROUP BY order_office_id
OR statement in your ON condition caused the problem.

Related

name and sum from 2 different tables

I have 2 tables.
table customer have. id , name , age
table order have . id, customer_id , order_amount , order date.
I want to show all name from customer table and sum of order amount from order table according to customer.
customer_id
Name
age
1
Alice
24
2
Bob
52
3
Carol
45
4
Dave
51
order_id
customer_id
order_amount
order_date
1
2
50
2012-4-5
2
1
27
2012-8-1
3
2
12
2013-5-20
4
4
25
2014-1-25
5
4
30
2014-5-30
6
1
20
2014-6-22
EDIT
I tried this but it gives me only bob and sum of all columns instead of separate sum of customers
SELECT customers.name, SUM(orders.order_amount) FROM `orders` INNER JOIN customers WHERE orders.customer_id = customers.customer_id;
Joining condition must be on ON clause, not in WHERE.
You must specify for what group the sum must be calculated.
SELECT customers.name, SUM(orders.order_amount)
FROM `orders`
INNER JOIN customers ON orders.customer_id = customers.customer_id
GROUP BY customers.name;

How to get right sum from inner join in mysql

I have two tables one is orders and second is order_product in which I have to find out orders count, product count, totalamount in corresponding to store using store id from which I have successfully find out the orders count and product count but my totalamount is not coming correct.
orders:
...........................
order_id or_total_amt
...........................
1 10
2 10
3 10
order_product
.................................
op_id op_order_id st_id
.................................
1 1 1
2 2 2
3 3 1
4 3 1
I want below output but my totalamount value is coming wrong it is coming 30,but the correct value is 20 which i have mentioned in the right output below.
output which i want:
.........................................
st_id orders product totalmount
.........................................
1 2 3 20
2 1 1 10
I have tried the below query which is giving 30 value of totalamount which is wrong.
SELECT `op_st_id`,count(distinct orders.`order_id`)as orders,count(order_product.op_pr_id) as product
,sum(orders.or_total_amt) as totalamount from orders
inner JOIN order_product on orders.order_id=order_product.op_order_id
group by `op_st_id`
SELECT
`st_id`,
count(DISTINCT orders.`order_id`) AS orders,
count(order_product.op_id) AS product,
count(DISTINCT orders.`order_id`)*(sum(orders.or_total_amt)/count(order_product.op_id)) AS totalamount
FROM
orders
INNER JOIN order_product ON orders.order_id = order_product.op_order_id
GROUP BY
`st_id`

mysql: two table join with sum

I'm attempting to join two tables and also get a SUM and flailing badly. I need to get the total commission amounts for each affiliate where affiliate.approved=1 AND order.status=3.
//affiliate table
affiliate_id | firstname | lastname | approved |
1 joe shmoe 1
2 frank dimag 0
3 bob roosky 1
here's the order table
//order
affiliate_id | order_status_id | commission
1 3 0.20
1 0 0.30
2 3 0.10
3 3 0.25
1 3 0.25
2 3 0.15
2 0 0.20
and here's what I'd like the query to return:
affiliate_id | commission
1 0.45
3 0.25
Here is my attempt that doesn't work. It outputs just one line.
SELECT order.affiliate_id, SUM(order.commission) AS total, affiliate.firstname, affiliate.lastname FROM `order`, `affiliate` WHERE order.order_status_id=3 AND affiliate.approved=1 AND order.affiliate_id = affiliate.affiliate_id ORDER BY total;
thanks for any help.
You've missed GROUP BY, try this:
SELECT
`order`.affiliate_id,
SUM(`order`.commission) AS total,
affiliate.firstname,
affiliate.lastname
FROM `order`
JOIN `affiliate`
ON `order`.order_status_id = 3 AND affiliate.approved = 1 AND `order`.affiliate_id = affiliate.affiliate_id
GROUP BY `order`.affiliate_id
ORDER BY total;
Demo Here
You can try this Query for your solution :-
SELECT order.affiliate_id, SUM(order.commission) AS total,affiliate.firstname,
affiliate.lastname
FROM `order`, `affiliate`
WHERE order.order_status_id=3
AND affiliate.approved=1
AND order.affiliate_id = affiliate.affiliate_id
GROUP BY order.affiliate_id
ORDER BY total;
Here is the solution:
select affiliate.affiliate_id,sum(`order`.commission) as total from affiliate left join `order` on affiliate.affiliate_id=`order`.affiliate_id
where affiliate.approved=1 and `order`.order_status_id=3 group by affiliate.affiliate_id
In addition,"order" is a key word of SQL , I recommend you not to use it as a table/column name.
First: Remove the implicit join syntax. It's confusing.
Second: You needed to group by affiliate_id. Using aggregate function without group by collapses your result set into a single row.
Here's the query using INNER JOIN:
SELECT
`order`.affiliate_id,
SUM(`order`.commission) AS total,
affiliate.firstname,
affiliate.lastname
FROM `order`
INNER JOIN`affiliate` ON `order`.affiliate_id = affiliate.affiliate_id
WHERE `order`.order_status_id = 3
AND affiliate.approved = 1
GROUP BY affiliate.affiliate_id
ORDER BY total;
WORKING DEMO
Caution: You have picked one of the reserved words of MySQL as table name (order). Be aware to enclose it with (`)backtick always .
Just a gentle reminder

MYSQL: View statement produces incorrect SUM totals

I have 3 tables. A table for product prices, invoiced products, and ordered products. I am trying to create a view that joins these. I want to output the product prices with a total of invoiced products and a total of ordered products.
products_price
id season_id product_id product_price
1 1 1 3.99
2 1 2 6.99
3 1 3 5.99
4 1 4 5.99
....
invoices_products
id season_id invoice_id product_id piece_qty
1 1 1 1 1600
2 1 2 2 3200
3 1 3 2 200
4 1 4 1 120
....
orders_products
id season_id order_id product_id piece_qty
1 1 1 1 160
2 1 2 1 40
3 1 2 2 20
4 1 3 2 10
....
Here are a few queries from the View statements I've tried so far.
This query gives me everything I want. The View's output is perfect but the SUM() for the first 2 rows is off. total_invoice_product is double for row 1 and 2. total_order_productis 4x for row 1 and 3x for row 2.
Statement 1:
SELECT
`t1`.`id` AS `id`,
`t1`.`season_id` AS `season_id`,
`t1`.`product_id` AS `product_id`,
`t1`.`product_piece_price` AS `product_piece_price`,
SUM(`t2`.`piece_qty`) AS `total_invoice_product`,
SUM(`t3`.`piece_qty`) AS `total_order_product`
FROM
((`products_price` `t1`
LEFT JOIN `invoices_products` `t2` ON (((`t2`.`product_id` = `t1`.`product_id`)
AND (`t2`.`season_id` = `t1`.`season_id`))))
LEFT JOIN `orders_products` `t3` ON (((`t3`.`product_id` = `t1`.`product_id`)
AND (`t3`.`season_id` = `t1`.`season_id`))))
GROUP BY `t1`.`season_id` , `t1`.`product_id`
This query gives me the output that I expect. Its not the full output I want but its correct for the statement. The SUM() totals are off on this one as well.
Statement 2:
SELECT
`t1`.`id` AS `id`,
`t1`.`season_id` AS `season_id`,
`t1`.`product_id` AS `product_id`,
`t1`.`product_price` AS `product_price`,
SUM(`t2`.`piece_qty`) AS `total_invoice_product`,
SUM(`t3`.`piece_qty`) AS `total_order_product`
FROM
((`products_price` `t1`
LEFT JOIN `invoices_products` `t2` ON ((`t2`.`product_id` = `t1`.`product_id`)))
LEFT JOIN `orders_products` `t3` ON ((`t3`.`product_id` = `t1`.`product_id`)))
WHERE
((`t2`.`season_id` = `t1`.`season_id`)
AND (`t2`.`product_id` = `t1`.`product_id`))
GROUP BY `t1`.`season_id` , `t1`.`product_id`
the output I want
id season_id product_id product_price total_invoice total_order
1 1 1 3.99 1720 200
2 1 2 6.99 3400 30
3 1 3 5.99 576
4 1 4 5.99 800
output received for statement 1
id season_id product_id product_price total_invoice total_order
1 1 1 3.99 3440 800
2 1 2 6.99 6800 90
3 1 3 5.99 576
4 1 4 5.99 800
output received for statement 2
id season_id product_id product_price total_invoice total_order
1 1 1 3.99 3440 800
2 1 2 6.99 6800 90
I can build a query like below and it works perfect. I get the exact output I need but this code does not work as a view. I get this error: ERROR 1349: View's SELECT contains a subquery in the FROM clause SQL Statement
Perfect Query but will not work as a view
SELECT
products_price.id,
products_price.season_id,
products_price.product_id,
products_price.product_price,
invoices_grouped.total_invoice_product,
orders_grouped.total_order_product
FROM
products_price
LEFT JOIN
(SELECT
invoices_products.product_id,
invoices_products.season_id,
SUM(invoices_products.piece_qty) AS total_invoice_product
FROM
invoices_products
GROUP BY
invoices_products.product_id) AS invoices_grouped
ON
invoices_grouped.product_id = products_price.product_id
AND
invoices_grouped.season_id = products_price.season_id
LEFT JOIN
(SELECT
orders_products.product_id,
orders_products.season_id,
SUM(orders_products.piece_qty) AS total_order_product
FROM
orders_products
GROUP BY
orders_products.product_id) AS orders_grouped
ON
orders_grouped.product_id = products_price.product_id
AND
orders_grouped.season_id = products_price.season_id
What I need
I've tried several other statements. They either got worse results or the same. Can someone help me get Statement 1 working with a proper SUM?
Edit 1 for a question
The information that this view provides will be called upon a lot. The products_price and invcoices_products tables will not be changed that often. orders_products will be changed a lot. If 2 views are required, would it be more efficient to use the "Perfect" query above or use 2 views?
Edit 2 for another query
Here is another query from my view statement. This query is part of Statement 1 shown above. This query works perfect but it is not complete. I need the second SUM column. When you add the second LEFT JOIN it breaks the SUM totals.
SELECT
`t1`.`id` AS `id`,
`t1`.`season_id` AS `season_id`,
`t1`.`product_id` AS `product_id`,
`t1`.`product_piece_price` AS `product_piece_price`,
SUM(`t2`.`piece_qty`) AS `total_invoice_product`
FROM
(`products_price` `t1`
LEFT JOIN `invoices_products` `t2` ON (((`t2`.`product_id` = `t1`.`product_id`)
AND (`t2`.`season_id` = `t1`.`season_id`))))
GROUP BY `t1`.`season_id` , `t1`.`product_id`
output
id season_id product_id product_price total_invoice
1 1 1 3.99 1720
2 1 2 6.99 3400
3 1 3 5.99 576
4 1 4 5.99 800
Well, MySql has some limitations, so you will need to create 2 views for subqueries and use them:
create view viewInvoices
as
select season_id, product_id, sum(piece_qty) pq
from invoices_products group by season_id, product_id
create view viewOrders
as
select season_id, product_id, sum(piece_qty) pq
from orders_products group by season_id, product_id
select pp.id,
pp.season_id,
pp.product_id,
pp.product_price,
i.pq as total_invoice,
o.pq as total_order
from products_price pp
left join viewInvoices as i
on pp.season_id = i.season_id and pp.product_id = i.product_id
left join viewOrders as o
on pp.season_id = o.season_id and pp.product_id = o.product_id
Try this query
SELECT * from products_price as a left join (select product_id, sum(piece_qty)total_invoices from invoices_products group by product_id) as b on a.product_id=b.product_id left join (select product_id, sum(piece_qty) as total_order from orders_products group by product_id) as c on a.product_id=c.product_id

MySQL join with a subquery

I have three tables and am trying to get info from two and then perform a calculation on the third and display all the results in one query.
The (simplified) tables are:
table: employee_work
employee_id name
1 Joe
2 Bob
3 Jane
4 Michelle
table: carryover
employee_id days
1 5
2 10
3 3
table: timeoff
employee_id time_off_type days
1 Carryover 2
1 Leave 3
1 Carryover 1
2 Sick 4
2 Carryover 4
3 Leave 1
4 Sickness 4
The results I would like are:
employee_id, carryover.days, timeoff.days
1 5 3
2 10 4
3 3 0
However when I run the query, whilst I get the correct values in columns 1 and 2, I get the same number repeated in the third column for all entries.
Here is my query:
Select
employee_work.employee_id,
carryover.carryover,
(SELECT SUM(days) FROM timeoff WHERE timeoff.time_off_type = 'Carryover'
AND timeoff.start_date>='2013-01-01') AS taken
From
carryover Left Join
employee_work On employee_work.employee_id = carryover.employee_id Left Join
timeoff On employee_work.employee_id = timeoff.employee_id Left Join
Where
carryover.carryover > 0
Group By
employee_work.employee_id
I have tried to group by in the sub query but I then get told "Subquery returns more than one row" - how can I ensure that the sub query is respecting the join so it only looks at each employee at a time so I get my desired results?
The answer to your question is to use a correlated subquery. You don't need to mention the timeoff table twice in this case:
Select
employee_work.employee_id,
carryover.carryover,
(SELECT SUM(days)
FROM timeoff
WHERE timeoff.time_off_type = 'Carryover' and
timeoff.start_date>='2013-01-01' and
timeoff.employee_id = employee_work.employee_id
) AS taken
From
carryover Left Join
employee_work On employee_work.employee_id = carryover.employee_id
Where
carryover.carryover > 0
Group By
employee_work.employee_id;
An alternative structure is to do the grouping for all employees in the from clause. You can also remove the employee_work table, because it does not seem to be being used. (You can use carryover.employee_id for the id.)
Select co.employee_id, co.carryover, et.taken
From carryover c Left Join
(SELECT employee_id, SUM(days) as taken
FROM timeoff
WHERE timeoff.time_off_type = 'Carryover' and
timeoff.start_date>='2013-01-01'
) et
on co.employee_id = et.employee_id
Where c.carryover > 0;
I don't think the group by is necessary. If it is, then you should probably have an aggregation function in the original query.