how to join tables and 2 select together - mysql

I have the following two queries, how can I join them together?
Query1:
SELECT product_name, count(product_name) as count_product_name
FROM ps_order_detail
WHERE id_shop = 1
group by product_name
order by count_product_name DESC
LIMIT 5
Query2:
SELECT count(*) as count, concat(decade, '-', decade + 9) as year
FROM (SELECT floor(year(`birthday`) / 10) * 10 as decade
FROM ps_customer) C
GROUP BY decade;
the first query is to get the top 5 product name that ordered the most.
the second query is get the customer birthday year and group them by every ten years.
I want to know the age group that order the top 5 product.
result should be
product name, years, count
productA 1990-2009 100
ProductA 2000-2019 20
ProductB 1980-1999 20
ProductB 1990-2009 25
ProductB 2000-2019 20
...
I do have a third table to have the connection.
create table ps_orders(
id_customer,
id_order
);
create table ps_customer(
id_customer, birthday
);
create table ps_order_detail(
id_order, product_name
);
I am not sure how to put them all together, I can input the product name one by one to get the years.
SELECT count(*) as count, concat(decade, '-', decade + 9) as year
FROM (SELECT floor(year(birthday) / 10) * 10 as decade
FROM ps_customer as CU,
ps_orders as O,
ps_order_detail as OD
WHERE CU.id_customer = O.id_customer
AND O.id_order = OD.id_order
AND OD.product_name = 'product Name A'
) C
GROUP BY decade;

Use your second query, but instead of specifying a particular product, put that into the grouping. Then join that with the subquery that returns the top 5 products to limit it.
SELECT product_name, concat(decade, '-', decade + 9) AS year, count(*) AS count
FROM (SELECT p.product_name, floor(year(birthday) / 10) * 10 as decade
FROM (SELECT product_name, count(*) as count_product_name
FROM ps_order_detail
WHERE id_shop = 1
group by product_name
order by count_product_name DESC
LIMIT 5) AS p
JOIN ps_order_detail AS od ON od.product_name = p.product_name
JOIN ps_orders AS o on o.id_order = od.id_order
JOIN ps_customer AS c ON c.id_customer = o.id_customer
WHERE od.id_shop = 1) AS x
GROUP BY product_name, decade

Related

select sum qty from 2 tables

In MySQL I have 4 tables:
- product(id)
- order(id)
- order_detail_1(id, product_id, order_id, qty)
- order_detail_2(id, product_id, order_id, qty)
I want to get the sum of the quantity of products sold from the 2 tables (order_detail_1, order_detail_2) grouping them by product
produt can existe in order_detail_1 and not in order_detail_2 and vice versa
i tested this query and it worked but I want a simpler query without the union and the subquery.
select tmp.product_id ,sum(tmp.qty) from
(
(
select order_detail_1.product_id ,sum(order_detail_1.qty)
from order_detail_1
inner join order on order_detail_1.id_order = order.id
where order_detail_1.product_id is not null
group by order_detail_1.product_id
)
union all
(
select order_detail_2.product_id ,sum(order_detail_2.qty)
from order_detail_2
inner join order on order_detail_2.id_order = order.id
where order_detail_2.product_id is not null
group by order_detail_2.product_id
)
) tmp
group by tmp.product_id
It looks like you're not using order table other then checking if it exists, so you can use EXISTS()
SELECT p.product_id,sum(p.qty) as qty
FROM (SELECT product_id,qty,id_order FROM order_detail_1
WHERE product_id IS NOT NULL
UNION ALL
SELECT product_id,qty,id_order FROM order_detail_2
WHERE product_id IS NOT NULL) p
WHERE EXISTS(SELECT 1 FROM order o
WHERE o.id = p.id_order)
GROUP BY p.product_id
If a product is in only one table, you can use left join:
select p.id, (coalesce(sum(od1.qty), 0) + coalesce(sum(od2.qty, 0))) as qty
from product p left join
order_detail_1 od1
on od1.product_id = p.id left join
order_detail_2 od2
on od2.product_id = p.id
group by p.id;
This formulation depends on the fact that the two tables are exclusion -- a product is in only one table.
EDIT:
If products can exist in both tables, then you need to aggregate them first:
select p.id, (coalesce(od1.qty, 0) + coalesce(od2.qty, 0)) as qty
from product p left join
(select product_id, sum(qty) as qty
from order_detail_1 od1
group by product_id
) od1
on od1.product_id = p.id left join
(select product_id, sum(qty) as qty
from order_detail_2 od2
group by product_id
) od2
on od2.product_id = p.id;

mysql INNER/LEFT JOIN with UNION ALL

I have a question regarding the use of UNION ALL and INNER JOIN.
I found some posts regarding this issue, for example here or there but I did not manage to apply it to my issue.
What I am trying to do is to list 1) the products and 2) the difference between orders and deliveries.
I have 3 table:
product (id, name)
orders (id, product, value)
deliveries (id, product, value)
I managed to get (almost) what I want using the following:
SELECT product
, sum(total)
FROM (
SELECT product
, SUM(value) as total
FROM orders
GROUP BY product
union all
SELECT product
, -1 * SUM(value) as total
FROM deliveries
GROUP BY product)
as alias
GROUP BY product
ORDER BY sum(total) DESC
I obtain the following:
1 23
2 33
When I would like to get:
computer 23
car 33
Meaning the product name instead of the product id.
Anyone would have a solution for that? (my INNER JOIN OR LEFT JOIN attempts failed so far)
Thanks and regards
Join in the product table:
SELECT p.name, sum(total)
FROM (SELECT o.product, SUM(o.value) as total
FROM orders o
GROUP BY o.product
union all
SELECT d.product, -1 * SUM(d.value) as total
FROM deliveries d GROUP BY d.product
) od JOIN
product p
on od.product = p.id
GROUP BY p.name
ORDER BY sum(total) DESC

sum sql group by values from another table

I've got 2 tables: Online Orders, Online orders details
I have an issue on how to calculate the total amount of the order in Online Order table based on the detail order table.
The detail table looks like:
id_order Id_product quantity price value
1 2 1 3 3
1 3 2 2 4
2 1 1 5 5
I would like to sum all the values from an id_order and insert them into the total amount of the order in the Online orders table.
Can you help me with the SQL command?
It's not clear what database system you use.
If you want to UPDATE orders.total_amount
This update statement will work under any DB:
update orders
set total_amount = (
select SUM(value)
from orders_details
where id_order = orders.id
)
where EXISTS(select *
from orders_details
where id_order = orders.id)
This update statement works under MySQL:
update orders u
inner join (select id_order, SUM(value) as total
from orders_details
GROUP BY id_order) s on
u.id = s.id_order
set u.total_amoun = s.total
Is this what you want?
SELECT o.id_order, SUM(quantity * price) AS total_price
FROM online o
INNER JOIN detail d
ON d.id_order = o.id_order
GROUP BY o.id_order

Getting both max and min sum values on mysql

Good day everyone I would like a query that can give me both maximum and minimum sum values. Specifically i have the following tables:
PRODUCT
_____________________________
productID | categoryID| name|
__________|___________|_____|
1 1 "name1"
2 1 "name2"
3 1 "name3"
4 2 "name4"
5 2 "name5"
6 1 "name6"
7 2 "name7"
8 2 "name8"
AND:
PURCHASES
_____________________________
purchaseID | productID| quantity|
___________|___________|_________|
1 1 12
2 2 13
3 4 55
4 4 66
5 5 99
6 6 99
7 5 88
8 7 12
so basically i have to show the product that was bought the most and the product that was bought the least.. T have tried this:
SELECT pr.name, max(sum(p2.quantity))
FROM purchase as p2, product as pr
WHERE p2.IDproduct=pr.IDproduct
Group by p2.IDproduct desc
but I get Error Code 1111: Invalid use of group function.
For max Product
select t.name,max(t.sum1) MaxProduct
FROM
(SELECT a.name, sum(b.quantity) sum1
FROM PRODUCT a
INNER JOIN PURCHASES b
ON a.productID = b.productID
GROUP BY a.productID )t
group by t.name order by MaxProduct desc limit 1
FOR COMBINE RESULT
(select t.name,max(t.sum1) MaxProduct
FROM
(SELECT a.name, sum(b.quantity) sum1
FROM PRODUCT a
INNER JOIN PURCHASES b
ON a.productID = b.productID
GROUP BY a.productID )t
group by t.name order by MaxProduct desc limit 1)
UNION ALL
(select t1.name,min(t1.sum1) MaxProduct
FROM
(SELECT a.name, sum(b.quantity) sum1
FROM PRODUCT a
INNER JOIN PURCHASES b
ON a.productID = b.productID
GROUP BY a.productID )t1
group by t1.name order by MaxProduct asc limit 1)
SQL FIDDLE
Hacky, but it works
(
SELECT
SUM(pur.quantity) quant,
prod.name name
FROM Purchases pur
INNER JOIN Products prod
ON prod.productID = pur.productID
GROUP BY pur.productID
ORDER BY quant DESC
LIMIT 1
)
UNION
(
SELECT
SUM(pur.quantity) quant,
prod.name name
FROM Purchases pur
INNER JOIN Products prod
ON prod.productID = pur.productID
GROUP BY pur.productID
ORDER BY quant ASC
LIMIT 1
)
SQLFiddle
As I received a Cannot perform an aggregate function on an expression containing an aggregate or a subquery as an error error.
For others encountering the problem of using the SUM function inside of a MAX function, but not having the same issue as OP, based on Luv's answer, I was able to convert the following Scalar-valued function:
SELECT #MinMaxValue = MAX(SUM(ArtikelM.Omzet)/SUM(ArtikelM.Aantal))
FROM ArtikelM
INNER JOIN Klanten
ON ArtikelM.KlantenId = Klanten.KlantenId
WHERE ArtikelId = #ArtikelId
AND Klanten.KlantTypeCategorie = #KlantType
AND Klanten.KlantGrootteCategorie = #KlantGrootte
AND ArtikelM.Jaar = #Jaar
to
SELECT #MinMaxValue = MAX(selectedsum.sumx)
FROM (
SELECT SUM(ArtikelM.Omzet)/SUM(ArtikelM.Aantal) AS sumx
FROM ArtikelM
INNER JOIN Klanten
ON ArtikelM.KlantenId = Klanten.KlantenId
WHERE ArtikelId = #ArtikelId
AND Klanten.KlantTypeCategorie = #KlantType
AND Klanten.KlantGrootteCategorie = #KlantGrootte
AND ArtikelM.Jaar = #Jaar
) AS selectedsum
or if ArtikelM.Aantal could be zero
SELECT sumx =
CASE
WHEN SUM(ArtikelM.Aantal) > 0
THEN SUM(ArtikelM.Omzet)/SUM(ArtikelM.Aantal)
ELSE MIN(Leverancier.FactPrijs)
END
FROM ArtikelM
INNER JOIN Leverancier
ON ArtikelM.LevId = Leverancier.LevId
INNER JOIN Klanten
ON ArtikelM.KlantenId = Klanten.KlantenId
WHERE ArtikelId = #ArtikelId
AND Klanten.KlantTypeCategorie = #KlantType
AND Klanten.KlantGrootteCategorie = #KlantGrootte
AND ArtikelM.Jaar = #Jaar
) AS selectedsum
I think this might help out others too
Select max(product_id), min(product_id)
from Purchases Where Product_id In
(select product_id, Sum(quantity) from Purchases Group by product_id)

MySQL - Looking for Top 10 records by Month

I will preface with Table Structures:
revshare r : contains info for a purchase including orderNo, sales, commission, itemid, EventDate
Products p: contains information around a product including a PID (Product ID) and is used to join to the Merchants table to get Merchant information.
Merchants m: contains information about the merchant the product was purchased from, including MerchantName
Question
I am trying to create a MySQL query to pull top 10 itemid's ordered by sum of commission for a given month. The entire data set I would like to get is from 2011-2013 so each year would populate 120 records (10 per month).
I created a query to pull 1 months worth of data and planned on using a UNION ALL to just create a records list with 10 records from each query (each individual query representing a months top 10 itemid's).
Query1
This query accurately returns me the top 10 itemid's based on total commission of those items in the given month period.
SELECT
m.MerchantName,
Count(r.OrderNo),
sum(r.commission)
FROM revshare r
LEFT JOIN Products p ON r.itemid = p.PID
LEFT JOIN Merchants m ON p.MID = m.MID
WHERE r.EventDate between '2011-01-01' and '2011-01-31'
GROUP by r.itemid
ORDER by 3 DESC LIMIT 10
When I try to UNION this query with another so that I can get records for the next month between '2011-02-01' and '2011-02-31' I get and error "ERROR: Incorrect usage of UNION and ORDER BY" I know this is because apparently you cannot use ORDER BY on any set of UNION'd queries but the last. I could pull the entire data set and then use Excel or Pentaho BI to show only the top 10 but that is not efficient based on the huge data sets in the revshare table.
Below is the query with the UNION ALL that doesn't work. Does anyone have any better method of pulling this data?
Any help is greatly appreciated.
Regards,
-Chris
Query 2 (doesn't work because of the ORDER BY statement)
SELECT
m.MerchantName,
Count(r.OrderNo),
sum(r.commission)
FROM revshare r
LEFT JOIN Products p ON r.itemid = p.PID
LEFT JOIN Merchants m ON p.MID = m.MID
WHERE r.EventDate between '2011-01-01' and '2011-01-31'
GROUP by r.itemid
ORDER by 3 DESC LIMIT 10
UNION ALL
SELECT
m.MerchantName,
Count(r.OrderNo),
sum(r.commission)
FROM revshare r
LEFT JOIN Products p ON r.itemid = p.PID
LEFT JOIN Merchants m ON p.MID = m.MID
WHERE r.EventDate between '2011-02-01' and '2011-02-31'
GROUP by r.itemid
ORDER by 3 DESC LIMIT 10
Ok, try this....
SELECT * FROM (
SELECT
m.MerchantName,
Count(r.OrderNo),
sum(r.commission)
FROM
revshare r
LEFT JOIN Products p ON r.itemid = p.PID
LEFT JOIN Merchants m ON p.MID = m.MID
WHERE
r.EventDate between '2011-01-01' and '2011-01-31'
GROUP by
r.itemid
ORDER by
3 DESC LIMIT 10
) AS RESULT1
UNION ALL
SELECT * FROM (
SELECT
m.MerchantName,
Count(r.OrderNo),
sum(r.commission)
FROM
revshare r
LEFT JOIN Products p ON r.itemid = p.PID
LEFT JOIN Merchants m ON p.MID = m.MID
WHERE
r.EventDate between '2011-02-01' and '2011-02-31'
GROUP by
r.itemid
ORDER by
3 DESC LIMIT 10
) AS RESULT2
Since you already started down the path of unioning queries together, here is the right approach:
select t.*
from ((SELECT '2011-01' as yyyymm, m.MerchantName, Count(r.OrderNo) as cnt, sum(r.commission) as comm
FROM revshare r LEFT JOIN
Products p
ON r.itemid = p.PID LEFT JOIN
Merchants m
ON p.MID = m.MID
WHERE r.EventDate between '2011-01-01' and '2011-01-31'
GROUP by r.itemid
ORDER by comm DESC
LIMIT 10
) union all
(SELECT '2011-02' as yyyymm, m.MerchantName, Count(r.OrderNo) as cnt, sum(r.commission) as comm
FROM revshare r LEFT JOIN
Products p
ON r.itemid = p.PID LEFT JOIN
Merchants m
ON p.MID = m.MID
WHERE r.EventDate between '2011-02-01' and '2011-02-28'
GROUP by r.itemid
ORDER by comm DESC LIMIT 10
) union all
. . .
) t
order by 1, comm desc
In other words, you need to use subqueries for the union all. Note that I also added in yyyymm to identify the month.