I have two MySql tables.
One of them stores general data about a product (name, image, description).
table name: product
table fields: id, name, desc, brand, image, status
The second one stores different variations about products (size, color, price, promotion price).
table name: product_variation
table fields: product_id, size, color, price, prom_price, status
The thing I don't realy know is how to display the products from the first table ordered by the prices from the second table, considering that in the second table there are more than one rows with the same product id, but different sizes, color and of course prices. By default the price field should be considered, but if there is a data larger then 0 in the prom_price field, than prom_price should be considered.
EDIT: the result I need is one instance of every product from the first table, with the lowest possible price from the second table (from all variations of that product in the second table)
SELECT * FROM product p
INNER JOIN product_variation pv
ON p.id = pv.product_id
ORDER BY pv.prom_price, pv.price
This will duplicate your product row for however many variants you have (and show all of these variants in the related fields as well). It orders by prom_price at first and if it's 0 (or not unique) then orders by price.
Edit: You might want to GROUP BY p.id if you want the products kept together.
This is one way of doing it, find the cheapest price on a product (price or prom_price) using a left join, and order by that price. The repeating CASE expressions would be easy to remove using common table expressions, but sadly, MySQL does not have those :-/
SELECT p.name FROM products p
JOIN product_variations pv1 ON p.id=pv1.product_id
LEFT JOIN product_variations pv2 ON pv1.product_id = pv2.product_id
AND CASE WHEN pv1.prom_price<>0 THEN pv1.prom_price ELSE pv1.price END >
CASE WHEN pv2.prom_price<>0 THEN pv2.prom_price ELSE pv2.price END
WHERE pv2.product_id IS NULL
ORDER BY CASE WHEN pv1.prom_price<>0 THEN pv1.prom_price ELSE pv1.price END;
An SQLfiddle to test with.
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!
I have 3 tables:
Store(sID, name, address, mID)
Sells(sID, pID)
Product(pID, name, manufacturer, price)
I need to find which stores stock every product from a given manufacturer. For example: to search Unilever, I'd expect to return only stores which stock ALL Unilever products listed in Product, not just some of them.
I've tried lots of different queries with most being completely off the mark.
Am I right in thinking I need to create a subset of all the products made by Unilever, then somehow go through Sells and check that the list of pIDs for each sID contain all of those in the initial subset? I can then join the result with Store to get the store details.
If that's the correct logic, where would one begin?
This creates a subset of all the unilever products:
SELECT pID FROM Product WHERE manufacturer = "Unilever"
How would I then check this list against each store in Sells to find the ones that contain all the products in the list?
One possible way is to join the product table twice, once via the sells table and once directly, then use COUNT(DISTINT ...) on each joined table to check they match
SELECT st.*
FROM store st
INNER JOIN sells se ON st.sID = se.sID
INNER JOIN product pr1 ON se.pID = pr1.pID AND pr1.manufacturer = "Unilever"
INNER JOIN product pr2 ON pr2.manufacturer = "Unilever"
GROUP BY st.sID,
st.name,
st.address,
st.mID
HAVING COUNT(DISTINCT pr1.pID) = COUNT(DISTINCT pr2.pID)
how about creating a Product column in Store table so that all you have to do is search for Unilever Product in the Store table. Then apply this:
SELECT Product FROM Store WHERE Product = "Unilever"
But of course you wouldnt want the column Product in your Store table so my answer cant be correct then
So I have two mySQL tables: products and prices. In products I have the informations about the product (id, name, type, date,...) and prices include informations for the prices for a products. i.E. product USB with ID CF003X from table products is available in tableprices with sellers (A, B, C and prices 18.00, 12.00, 13.50).
Now, when I want to select the highest price for a date, groupped by product IDs, the query returns the highest prices, but doesnt show correctly from which seller.
I also want to get results where i.E. seller 'Asus' had the highest price1
SQL Fiddle
This is a typical example where subqueries can be used: create a subquery that returns the highest price for product in a certain data range, then join this back to the prices table and get the supplier(s) who supply at that price. The date range, however, should probably be in the prices table, not in the products one. Prices change, products not really (they can be flagged as not to be listed). You should also consider having a product and a pricing id in the pricing table.
However, I'm going along with the fields you supplied within the sqlfiddle example.
select prod.id, p.seller, p.price1, p.price2
from prices p
inner join (select id, max(price1) as maxprice from prices group by id) mp on p.id=mp.id and p.price1=mp.maxprice
inner join products prod on p.id=prod.id
where prod.date='...'
You can extend the above query to show a specific vendor only by adding that vendor to the where criteria.
Pretty new to sql statements here so this one is a bit tricky for me.
I have two tables: sold and product. Sold(SID, UPC, Date) Product(UPC, Name, Brand)
I need to find in how many stores(sid) does one brand outsell another brand.
I was thinking it was something like:
select count(*) from sold natural join product
where count(brand = 'sony') > count(brand = 'samsung');
Clearly that isn't valid however...
SELECT COUNT(*)
FROM (
SELECT SID
FROM Sold
JOIN product
ON product.UPC = Sold.UPC -- otherwise we have a cartesian product
GROUP BY SID -- if we need totals _by store_, we need to group on that.
HAVING SUM(brand='sony') > SUM(brand='samsung')
) Totals.
I am trying to put together a mysql query, that links 3 tables together. In essence, the tables are as follows:
products - Contains product information and basic pricing.
product_depts - Linking table that links products to different departments.
promotions - Another linking table, links promotion periods and prices based on product id.
This is the query:
SELECT p.id, `desc` , price1, price2, cost1, taxable, quantity, deptId, sale
FROM products p
INNER JOIN product_depts ON p.id = prodId
INNER JOIN promotions s ON p.id = s.id
WHERE MATCH (
`desc`
)
AGAINST (
'CLOVER'
IN BOOLEAN
MODE
)
ORDER BY `desc`
LIMIT 0 , 30
If the following line is removed:
INNER JOIN promotions s ON p.id = s.id
And sale taken out of the select clause,
What happens, is ALL the products with a description containing "CLOVER", in the products table, are returned.
With the addition of the removed query parts, only the items that are on promotion (have a matching id in the promotions table), are returned. And any additional products containing "CLOVER" in the products table, that are not "on promotion" are left out.
As I have very limited knowledge with mysql, I thought maybe someone that does have a great deal of knowledge on the matter to share... Would like to provide some input with this.
As i understand it though, this would be essentially the same thing as calling deptId from the product_depts table, which works perfectly. So it is confusing me.
What am i doing wrong that only the items that are "on promotion" are displayed and the additional results are left out?
Thank you!
INNER joins basically say "retrieve all records where there's a matching record in BOTH tables".
If I'm reading your question correctly, it sounds like what you'd want is a LEFT or RIGHT join, which translates to "retrieve all records from one table, and (if any) matching records from the other table.
Sounds like you want to get all products, whether they have a promotion or not, but if they do have a promotion, retrieve the promo info as well.
That'd be
SELECT ...
FROM products
INNER JOIN product_depts ON ...
LEFT JOIN promotions ON ...
So... all products MUST have a department, so do an inner join for that particular part of the query. The left join on promotions makes the 'products' table be the LEFT table, so all records from that table are fetched. The promotions table becomes the RIGHT table, and only provides data for the query results if there's a matching record in the promotions table.
So... given 2 products, 1 of which is on sale, you'd get
product #1 department #1 promoinfo #1
product #2 department #2 NULL
for results. Since there's no matching promo information for the #2 product, you get NULL for the promo data.