Select top sales products - mysql

I have three tables like this
orders(id, status, ...)
products(id, created_at, ...)
product_order(order_id, product_id, quantity)
I want to select the most sold products first then continue with latest products taking the quantity in consideration, Here's my try
SELECT products.* FROM products
LEFT JOIN product_order ON product_order.product_id = products.id
LEFT JOIN orders ON orders.id = product_order.order_id
WHERE orders.status != 'REJECTED'
GROUP BY product_order.product_id
ORDER BY COUNT(*) DESC, products.created_at
This statement returns the products that are not sold first because I am using left join and they count more than the sold ones.. also I don't know how to take the quantity in consideration
Thank you,

This should work :
SELECT p.*, sum(po.quantity) qty
FROM products p
LEFT OUTER JOIN product_order po ON po.product_id = p.id
LEFT OUTER JOIN orders o ON o.id = po.order_id
WHERE o.status != 'REJECTED'
GROUP BY po.product_id
ORDER BY qty DESC, p.created_at

If you want the most sold products you could add
AND products.quantity = SELECT max(quantity) from products
after your WHERE statement

Related

Mysql query for sum two table data by product wise

If I use the below code the sum of sale and purchase product wise perfect but 5 NO product missing because no purchase only sale but I want to show all product. what-ever purchase or sale are zero.
SELECT *
FROM (
SELECT product_id, SUM(quantity) AS sale
FROM order_item group by product_id
) P
JOIN (
SELECT product_id, SUM(quantity) AS purchase
FROM pur_item
group by product_id
) S
JOIN (
SELECT product_id as Pid
FROM product GROUP BY Pid
) I ON I.Pid = P.product_id AND S.product_id = P.product_id
If is use below code then result is like below. I don't know sum of sale and purchase is not perfect.
select p.product_id, sum(s.quantity) sale, sum(c.quantity) purchase
from product p
left join pur_item c on c.product_id = p.product_id
left join order_item s on s.product_id = p.product_id
where c.quantity is not null or s.quantity is not null
group by p.product_id
I want result for all item sum of product wise data what ever sale or purchase made.
You are taking the correct approach in your first query but your JOIN conditions are wrong and you need to use LEFT JOINs instead of JOIN to get products which have no purchases or no sales:
SELECT I.product_id,
COALESCE(S.sale, 0) AS sale,
COALESCE(P.purchase, 0) AS purchase
FROM Product I
LEFT JOIN (
SELECT product_id, SUM(quantity) AS sale
FROM order_item
GROUP BY product_id
) S ON S.product_id = I.product_id
LEFT JOIN (
SELECT product_id, SUM(quantity) AS purchase
FROM pur_item
GROUP BY product_id
) P ON P.product_id = I.product_id
We also use COALESCE to convert NULL values (when a product has no purchases or sales) to 0.

MySQL - products list table and group prices

I have two tables:
products table: id, name, price
prices table: id, product_id, group_id, price
Query:
SELECT p.id, p.name, p.price, pr.price AS newPrice, pr.id AS prID
FROM products p
LEFT JOIN prices pr ON pr.product_id = p.id
WHERE pr.group_id = '1'
ORDER BY p.id ASC
I need see all products and if filled prices than get result from prices table.
But I see only filled datas, when I'm writing "WHERE"
Sorry for my English
When using LEFT JOINThe filter on the prices table should be placed at the ON clause
SELECT p.id, p.name, p.price, pr.price AS newPrice, pr.id AS prID
FROM products p
LEFT JOIN prices pr ON pr.product_id = p.id AND pr.group_id = 1
ORDER BY p.id ASC

Replacing id with name form another table in existing query

here's my query for getting the remaining stocks of each Product_Id. However, I'm not sure how to go about adding Product_Name from Product table. I just want to replace the i.Product_Id with p.Product_Name with p being the alias of Product. I know that the Product p should be inserted in the FROM but not sure how to connect it with the given query.
By the way, Product.Id = Inventory.Product_Id
SELECT
i.Product_Id,
i.Stocks,
s.Sales,
i.Stocks - s.Sales AS Remaining
FROM (SELECT product_id, COALESCE(SUM(quantity),0) AS Stocks FROM inventory GROUP BY product_id) i
LEFT JOIN (SELECT product_id, COALESCE(SUM(quantity),0) AS Sales FROM sales_detail GROUP BY product_id ) s
USING(product_id);
Thanks in advance guys!
UPDATE!!
The query below is my updated one, can someone check if I linked the product correctly with the existing JOIN USING, thanks!
SELECT
i.Product_Id,
p.Product_Name,
i.Stocks,
s.Sales,
i.Stocks - s.Sales AS Remaining
FROM (SELECT product_id, COALESCE(SUM(quantity),0) AS Stocks FROM inventory GROUP BY product_id) i
LEFT JOIN (SELECT product_id, COALESCE(SUM(quantity),0) AS Sales FROM sales_detail GROUP BY product_id ) s
USING(product_id)
JOIN Product p
ON i.Product_Id=p.Id;
You just need to JOIN with the Products table.
SELECT
p.Product_Name,
i.Stocks,
s.Sales,
i.Stocks - s.Sales AS Remaining
FROM (SELECT product_id, COALESCE(SUM(quantity),0) AS Stocks FROM inventory GROUP BY product_id) i
JOIN Products AS p USING (product_id)
LEFT JOIN (SELECT product_id, COALESCE(SUM(quantity),0) AS Sales FROM sales_detail GROUP BY product_id ) s
USING(product_id)

SQL Join Constraint Column on Another Joined Table

So practically I have 3 tables:
products
id
orders
id
status
order_items
id
order_id
product_id
quantity
So I want to query by products table as the main one. I want to know how many each one has been ordered, hence
SELECT products.*, SUM(order_items.quantity) AS sale_count
FROM products
LEFT JOIN order_items ON products.id = order_items.product_id
GROUP BY products.id
Everything works fine, no problem. But this query will count any order_items for each row, now I want to count only if the order status is done. But the problem is to get the status of that order_items you need to reference orders right?
SELECT products.*, SUM(order_items.quantity) AS sale_count
FROM products
LEFT JOIN order_items ON products.id = order_items.product_id
LEFT JOIN orders ON order_items.order_id = orders.id AND orders.status = 'done'
GROUP BY products.id
But this doesn't make a constraint on the order_items instead only order which has the status of done will be shown in the table else NULL.
How to approach this problem? Thank you for your kind help. I really appreciate it!!
It's not 100% clear to me what you are asking, but I think you are asking how to count orders for which the order status is done without throwing out results for which the order status is not done. If so, then the following should work:
SELECT products.*,
SUM(CASE WHEN orders.status = 'done'
THEN order_items.quantity
ELSE 0 END) AS sale_count
FROM products
LEFT JOIN order_items
ON products.id = order_items.product_id
LEFT JOIN orders
ON order_items.order_id = orders.id
GROUP BY products.id
I think you just want conditional aggregation:
SELECT p.*,
SUM(CASE WHEN o.status = 'done' THEN order_items.quantity END) AS sale_count
FROM products p LEFT JOIN
order_items oi
ON p.id = oi.product_id LEFT JOIN
orders o
ON oi.order_id = o.id
GROUP BY p.id;
I moved the 'done' condition to a case statement. You can leave it in the on clause as well, if you like. I just think this logic is more explicit about your intention.

MySQL count group by

I have 3 tables, orders(orders_id, date, ...), products (product_id, product_name, product_price) and order_products (product_id, orders_id, product_id, products_quantity) and I need to group the products so that they are displayed by product and total quantity per product to make it easier for the eshop manager to know how many items per product have been ordered.
I'm having a little bot of trouble thinking of the correct sql syntax, I keep bumping into group by issues and i'd like some help.
This is what I've done so far
select *, op.products_quantity as pquant, count(*) as `count`
from orders o
left join orders_products op on o.orders_id = op.orders_id
left join products p on op.products_id = p.products_id
group by op.orders_products_id
order by op.products_id desc;
Looking at what you have, you're counting orders, not summing the quantity of the orders..
So
if you had
orders
monday 5 potatoes
tuesday 2 carrots
wednesday 3 potatoes
You wanted
potatoes 8
carrots 2
in which case you'd want to do
select sum(quantity),item from orders group by item
I didnt quite see what the differende between orders_products and orders was.
Maybe a bit of sample data would help?
Select p.Product_name,sum(prodcuts_quantity) as OrderedQuantity from
Order_products op join
Products p on p.Product_id = op.product_id
group by p.Product_name
If you need Total quantity and total orders per product than you can do that in following way
SELECT p.*,op.total_order,op.total_quantity FROM PRODUCT LEFT JOIN (SELECT COUNT(*) AS total_order, SUM(quantity) AS total_quantity FROM orders_products GROUP BY product_id) AS op ON p.id = op.product_id
This should work, use SUM, not COUNT:
SELECT
*,
SUM(op.products_quantity)
FROM
orders AS o
LEFT JOIN orders_products AS op ON o.orders_id = op.orders_id
LEFT JOIN products AS p ON op.products_id = p.products_id
GROUP BY p.products_id
ORDER BY p.products_id DESC