I am trying to get the most sold products list by making a mysql query . The problem is its still getting all of the data even after i use count .
select
mf.*,
od.*,
count(od.product_id) as product_count
from masterflight mf ,
order_details od
where od.product_id=mf.ProductCode
group by od.product_id
order by product_count
Here masterflight is the table where the product details are stored with their ids . And order_details is the table where record of each product being sold individually are stored . What i was trying to put in a logic that suppose a product with id 2 is sold 4 times and each time it has a separate entry then i would count those using COUNT and then display it which does it seems to be working .
Try something a little neater:
select
mf.ProductCode,
count(od.*) as product_count
from
order_details od
inner join masterflight mf on
od.product_id = mf.ProductCode
group by
mf.ProductCode
order by product_count desc
The problem is that you're selecting all of od, but you're not grouping by it, so you're just getting all of the order rows, which doesn't help you really at all. I should note that MySQL is the only one of the major RDBMSes that allows that behavior--and it's confusing and tough to debug. I'd advise against using that particular feature. As a general rule, if you've selected a column but don't have an aggregate (e.g.-sum, avg, min, etc.) on it, then you need it in the group by clause.
Related
I want to pull out from the Magento 2 database products sold in specific period and from specific product groups (Magento is not set to flat catalog table).
This is what I came up with
SELECT
SUM(qty_ordered) AS total
, sku
, name
, price
FROM(
SELECT
so.increment_id
,soi.product_id
,soi.order_id
,soi.sku
,soi.name
,soi.qty_ordered
,soi.price
FROM sales_order AS so
INNER JOIN sales_order_item AS soi ON soi.order_id = so.entity_id
WHERE so.created_at between '2022-11-11 00:00:00' AND '2022-11-13 23:59:59'
) AS soi
INNER JOIN catalog_category_product AS ccp
ON ccp.product_id = soi.product_id
-- The issue is in this where clause
WHERE category_id IN
(
5
)
GROUP BY sku, NAME, price
ORDER BY total desc
This works pretty well (optimization tips are highly welcomed of course), however, when I specify multiple categories in WHERE clause, the results gets multiplied by the number of categories that product belongs to.
So for example, if the product is in Makeup(id:5)->Eyes(id:6)->Eyeliners(id:7), and when clause says WHERE category_id IN (5,6,7) the data for the sold product is multiplied by 3, which is understandable, correct, but not what I'm looking for.
Yes, the product category should be by definition at least in the "root" category, but sometimes thats not the case. E.g. product is set only in Eyeliners(id:7), but not in its parent category Makeup(id:5).
So my question is what should I change to be able to specify multiple categories, and have them grouped by a single category instead multiplied by the amount of categories assigned to the product? (creating the controler and do it within the Magento code currently is not an option).
Any input is highly appreciated.
Thanks!
Well, I am struggling with this question in SQL using MySql:
I have to give the product that was mostly sold per supplier from the popular open source database called NORTHWIND: https://northwinddatabase.codeplex.com
Now what I wrote is:
SELECT products.SupplierID ,`order details`.ProductID, count(*) as NumSales FROM `order details`
JOIN products ON `order details`.ProductID = products.ProductID
JOIN orders ON `order details`.OrderID = orders.OrderID
WHERE `order details`.OrderID
IN
(SELECT OrderID FROM orders
WHERE MONTH(OrderDate) = 7 AND YEAR(orderDate) = 1997)
group by products.SupplierID , `order details`.ProductID
ORDER BY NumSales desc
;
The result is:
that this is all good but I need to give back for example for Supplier 1 Product 1 since it was sold 3 times (at 7/1997)
Adding to the start:
SELECT SupplierID, ProductID, MAX(b.NumSales)
FROM( ... )
gets me closer but it gives my the highest of all suppliers and not for every supplier.
Help will be great.
P.S.
This question is similar but the same and didn't completely help me.
Please know this as a psuedo answer and work with it as you will...appreciate that you are putting in the time to learn this.
select supplier_id, max(num_sales) max_sales
from (put your select statement here)
group by supplier_id
This now gives you what you max num_sales is for each supplier. Something like
supplier_id max_sales
1 3
2 1
3 2
4 2
Now join this back to your original query to get the product data for the whatever matches to the max.
select a.supplier_id, b.product_id, a.max_sales
from
(select supplier_id, max(num_sales) max_sales
from (put your select statement here)
group by supplier_id) a
inner join
(your original query again) b
on a.supplier_id = b.supplier_id
and a.max_sales = b.num_sales
As you learn SQL, you will see that there is usually hundreds of valid working scripts that will give you the answer you want....your job is to find the script that is the quickest to write, the most efficient to run, and meets the criteria of your task. The advantage to the method shown here is it will display multiple records in the event of a tie (supplier_id = 2 has two product that bot have a max sales of one. This query returns both those rows).
just as additional info...other databases allow common table expressions (with clause), however mysql does not. How do you use the "WITH" clause in MySQL? in other databases you are able to simplify this script further.
I have 3 tables:
1. products(product_id,name)
2. orders(id,order_id,product_id)
3. factors(id,order_id,date)
I want to retrieve product names(products.name) where have similar order_id on a date in two last tables.
I use this query for this purpose:
select products.name
from products
WHERE products.product_id ~IN
(
SELECT distinct orders.product_id FROM orders WHERE
order_id IN (select order_id FROM factors WHERE
factors.datex ='2017-04-29') GROUP BY product_id
)
but no result. where is my mistake? how can I resolve that? thanks
Your query should be fine. I am rewriting it to make a few changes to the structure, but not the logic (this makes it easier for me to understand the query):
select p.name
from products p
where p.product_id in (select o.product_id
from orders o
where o.order_id in (select f.order_id
from factors f
where f.datex = '2017-04-29'
)
) ;
Notes on the changes:
When using multiple tables in a query, always qualify the column names.
Use table aliases. They make queries easier to write and to read.
SELECT DISTINCT and GROUP BY are unnecessary in IN subqueries. The logic of IN already handles (i.e. ignores) duplicates. And by explicitly including the operations, you run the risk of a less efficient query plan.
Why might your query not work?
factors.datex has a time component. If so, then this will work date(f.datex) = '2017-04-29'.
There are no factors on that date.
There are no orders that match factors on that date.
There are no products in the orders that match the factors on that date.
In factors table column name is date so it should be -
factors.date ='2017-04-29'
You have written -
factors.datex ='2017-04-29'
Thank you for taking a look at my question! I've been trying to figure out a single query to do the following but have been unsuccessful. I would truly appreciate any help. Thank you in advance :-)
I am making an admin page for my e-commerce store that shows products that haven't sold in the last X days. There are three tables that need to be used...
Table: products
Column: product_id (int)
This table/column contains all the products in the store
Table: orders
Columns: order_id (int), date_ordered (datetime)
This table contains all the orders which are identified by order_id and the date for which they were ordered (date_ordered).
Table: order_products
Column: order_id (int), product_id (int)
This table contains a complete listing of all products ordered (product_id) and the corresponding order (order_id).
So, the query I'm trying to figure out would use use the order_id in tables orders and order_products to determine which products have sold in the last X days... Then return any products_id from the products table which have not sold in the last X days.
Any suggestions? Any help would be very appreciated! Thank you :-)
Okay so while I agree in part that you should do some poking around and learn more about left joins, there is also some trickiness to answering this question correctly that might be lost on a beginner. I'm gonna go ahead and help you answer it, but I would recommend learning more about joins.
My exact query would depend on the available indices, but it very likely resemble something like this:
SELECT a.*
FROM products AS a
LEFT JOIN (
SELECT product_id FROM order_products as b
INNER JOIN orders AS c
ON b.order_id = c.order_id
WHERE c.date_ordered >= date_sub(c.date_ordered, INTERVAL 7 day)
GROUP BY product_id
) AS d
ON a.product_id = d.product_id
WHERE d.product_id IS NULL
What I'm doing is I'm writing a subquery that joins orders and orders products together, where date_ordered falls within a certain date range (I would recommend learning about the date_sub function here: http://www.w3schools.com/sql/func_date_sub.asp and also do a few quick SELECT date_sub(date_ordered, INTERVAL X DAY) FROM orders queries to make sure you understand how this calculation works, in practice.
Now, I get my list of orders for the last X days (7 in the query above) and I join it with the orders product table to get the products that were ordered. Here, I want to dedup my products, basically. Product_id = 300 may have been ordered 70 times. Product_id = 200 may have been ordered 50 times. Whatever the case may be, I don't want to join 70 records and 50 records to my product table for product ids 300 and 200, so I dedup them. That last GROUP BY statement does that. It's functionally the same thing as writing DISTINCT (although there can be minor differences in how these are computed in certain circumstances, none of those circumstances seem to apply here... use DISTINCT if that's clearer for you)
Once I have my list of unique product ids that were ordered in the past X days, I join that with my product table. Here, I use a left join. Like the comments noted above, you'll want to look into the notion of joins pretty carefully. Do that, if you haven't already.
Last, I apply a WHERE filter that says "WHERE d.product_id IS NULL." What this is doing is saying, "okay, if product_id = Y was ordered in the past X days, then it will join to my products table successfully with a.product_id = d.product_id. If it wasn't ordered, then a.product_id will exist in my result set, but d.product_id won't. That is, d.product_id will be null."
That last twist may be the part that's not apparent / standing out.
Hope this helps.
I have 3 tables:
Orders
- id
- customer_id
Details
- id
- order_id
- product_id
- ordered_qty
Parcels
- id
- detail_id
- batch_code
- picked_qty
Orders have multiple Details rows, a detail row per product.
A detail row has multiple parcels, as 10'000 ordered qty may come from 6 different batches, so goods from batches are packed and shipped separately. The picked quantity put in each parcel for a detail row should then be the same as the ordered_qty.
... hope that makes sense.
Im struggling to write a query to provide summary information of all of this.
I need to Group By customer_id to provide a row of data per customer.
That row should contain
Their total number of orders
Their total ordered_qty of goods across all orders
Their total picked_qty of goods across all orders
I can get the first one with:
SELECT customer_id, COUNT(*) as number_of_orders
FROM Orders
GROUP BY Orders.customer_id
But when I LEFT JOIN the other two tables and add the
SELECT ..... SUM(Details.ordered_qty) AS total_qty_ordered,
SUM(Parcels.picked_qty) AS total_qty_picked
.. then I get results that dont seem to add up for the quantities, and the COUNT(*) seems to include the additional lines from the JOIN which obviously then isn't giving me the number of Orders anymore.
Not sure what to try next.
===== EDIT =======
Here's the query I tried:
SELECT
customer_id,
COUNT(*) as number_of_orders,
SUM(Details.ordered_qty) AS total_qty_ordered,
SUM(Parcels.picked_qty) AS total_qty_picked
FROM Orders
LEFT JOIN Details ON Details.order_id=Order.id
LEFT JOIN Parcels ON Parcels.detail_id=Detail.id
GROUP BY Orders.customer_id
try COUNT(distinct Orders.order_id) as number_of_orders,
as in
SELECT
customer_id,
COUNT(distinct Orders.order_id) as number_of_orders,
SUM(Details.ordered_qty) AS total_qty_ordered,
(select SUM(Parcels.picked_qty)
FROM Parcels WHERE Parcels.detail_id=Detail.id ) AS total_qty_picked
FROM Orders
LEFT JOIN Details ON Details.order_id=Order.id
GROUP BY Orders.customer_id
EDIT: added an other select with subselect
Is there any particular reason you feel the need to combine all these in one query? Simplify by breaking it up in to separate queries, and if you want a single call to get the results, put the queries in a stored procedure, using temp tables.