How to use Group by in mysql - mysql

I'm using this sql query to get the product list from DB.
SELECT distinct P.product_id, B.brand_name, P.product_name, P.product_description, SC.sub_category_name, P.product_image_path
FROM table_products as P
INNER JOIN table_brands as B
ON P.brand_id = B.brand_id
INNER JOIN table_product_categories as PC
ON P.product_id = PC.product_id
INNER JOIN table_subcategories as SC
ON SC.sub_categories_id = PC.category_id
INNER JOIN table_subcategory_categories as SCC
ON SC.sub_categories_id = SCC.subcategory_id
ORDER BY P.product_id DESC";
It works fine for me. But when same product is in multiple subcategories. It gives me a new row. I just wanted to avoid this and wants GROUP by with SC.sub_category_name. So when a product is in multiple categories, all the categories should list in same row.
Current
853 Tops Premium Vermicelli /images/tops/853.png Noodles
853 Tops Premium Vermicelli /images/tops/853.png Vermicelli
Expecting
853 Tops Premium Vermicelli /images/tops/853.png Noodles, Vermicelli

You can use GROUP_CONCAT() for that purpose, grouping by SC.sub_category_name and remove the distinct. Something like
SELECT P.product_id,
B.brand_name,
P.product_name,
P.product_description,
GROUP_CONCAT(SC.sub_category_name) as sub_cat_list,
P.product_image_path
FROM table_products P
INNER JOIN table_brands B
ON P.brand_id = B.brand_id
INNER JOIN table_product_categories PC
ON P.product_id = PC.product_id
INNER JOIN table_subcategories SC
ON SC.sub_categories_id = PC.category_id
INNER JOIN table_subcategory_categories SCC
ON SC.sub_categories_id = SCC.subcategory_id
GROUP BY P.product_id
ORDER BY P.product_id DESC;

Related

How Can I join multiple tables with information i want?

I'm using mysql 8.0.31 version.
Below is my database schema ERD.
I want to get inforamtion about products from my DB.
Below is my sql raw query.
SELECT
p.id, p.name, sc.name sub_category, c.name category, count(po.color_id) color_count
FROM products p
INNER JOIN sub_categories sc
ON sc.id = p.sub_category_id
INNER JOIN categories c
ON sc.category_id = c.id
LEFT JOIN products_options po
ON po.product_id = p.id
INNER JOIN genders g
ON po.gender_id = g.id
WHERE c.id = 1
GROUP BY p.id
ORDER BY p.id ASC;
I want to join products table with sub_categories, categories to get categories information about my products AND products table with products_options, colors, genders to get color_count about a product and gender type about a product.
So I wanted to query like this added g.type (gender type information for a product)
SELECT
p.id, p.name, sc.name sub_category, c.name category, count(po.color_id) color_count, g.type
FROM products p
INNER JOIN sub_categories sc
ON sc.id = p.sub_category_id
INNER JOIN categories c
ON sc.category_id = c.id
LEFT JOIN products_options po
ON po.product_id = p.id
INNER JOIN genders g
ON po.gender_id = g.id
WHERE c.id = 1
GROUP BY p.id
ORDER BY p.id ASC;
But this occurs error like this
SQL Error [1055] [42000]: Expression #6 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'mydb.g.type' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
I think this error occurs cuz I didn't use aggregate function for g.type.
Below is my result except g.type in sql select field.
I want to get genders.type field together.
I think I need to sub query and join that table created by sub query. But I don' t know well How can I implement that method.
To combine this gender type information, How can I modify my sql query?
I tried multiple method sql queries in various ways to join table.
You need to either remove the column from select list like:
SELECT p.id, count(po.color_id) color_count
FROM products p
INNER JOIN sub_categories sc
ON sc.id = p.sub_category_i`enter code here`d
INNER JOIN categories c
ON sc.category_id = c.id
LEFT JOIN products_options po
ON po.product_id = p.id
INNER JOIN genders g
ON po.gender_id = g.id
WHERE c.id = 1
GROUP BY p.id
ORDER BY p.id ASC;
or add in group by clause the select columns like:
SELECT p.id, p.name, sc.name sub_category, c.name category, count(po.color_id) color_count, g.type
FROM products p
INNER JOIN sub_categories sc
ON sc.id = p.sub_category_id
INNER JOIN categories c
ON sc.category_id = c.id
LEFT JOIN products_options po
ON po.product_id = p.id
INNER JOIN genders g
ON po.gender_id = g.id
WHERE c.id = 1
GROUP BY p.id,p.name, sc.name sub_category, c.name category, g.type
ORDER BY p.id ASC;

SQL LIKE seems not work like i think it should

I have an SELECT statement that has a huge number of left join and I want to filter some out.
When I check how many records i have in total and subtract the records with my LIKE statements, I should get the amount that is not affected by my restrictions.
But when I negate my restriction to get the ones I didn't affect, I get an different number than calculated.
SQL without restrictions (Record count: 13.251.981)
SELECT p.product_number
FROM product p
LEFT JOIN product_category pc on p.id = pc.product_id
LEFT JOIN product_category_tree pct on p.id = pct.product_id
LEFT JOIN product_configurator_setting pcs on p.id = pcs.product_id
LEFT JOIN product_cross_selling pcs2 on p.id = pcs2.product_id
LEFT JOIN product_cross_selling_assigned_products pcsap on p.id = pcsap.product_id
LEFT JOIN product_cross_selling_translation pcst on pcs2.id = pcst.product_cross_selling_id
LEFT JOIN product_custom_field_set pcfs on p.id = pcfs.product_id
LEFT JOIN product_media pm on p.id = pm.product_id
LEFT JOIN product_option po on p.id = po.product_id
LEFT JOIN product_price pp on p.id = pp.product_id
LEFT JOIN product_property pp2 on p.id = pp2.product_id
LEFT JOIN product_review pr on p.id = pr.product_id
LEFT JOIN product_search_keyword psk on p.id = psk.product_id
LEFT JOIN product_tag pt on p.id = pt.product_id
LEFT JOIN product_translation pt2 on p.id = pt2.product_id
LEFT JOIN product_visibility pv on p.id = pv.product_id
With restriction (Record count: 9.285.545)
WHERE p.product_number NOT LIKE 'SW%'
AND p.product_number NOT LIKE '%.%'
AND pt2.name NOT LIKE '%Gutschein'
AND pt2.name NOT LIKE '%Test%'
With negated restriction (Record count: 100.851)
WHERE p.product_number LIKE 'SW%'
OR p.product_number LIKE '%.%'
OR pt2.name LIKE '%Gutschein'
OR pt2.name LIKE '%Test%';
From my calculations i should get 3.966.436 records that don't get affected. (13.251.981 - 9.285.545 = 3.966.436)
But instead I get 100.851
How is that possible?
The solution for me was actually this WHERE:
WHERE p.product_number < 'SW'

How to use IN operator with AND operator in WHERE clause in SQL...?

I am using this database query in my CodeIgniter model.
SELECT
p.product_id,
p.product_name,
p.product_photo,
p.size,
p.price,
p.status,
p.product_image_path
FROM
products AS p
LEFT JOIN
product_category AS pc
ON
p.product_id = pc.product_id
LEFT JOIN
vendor_products AS vp
ON
vp.product_id = pc.product_id
WHERE
pc.category_id = 2
AND
vp.vendor_id = 36
AND
pc.subcategory_id IN (1,2)
AND
pc.subcategory_value_id IN (1,4)
And it returning me:
I want those products only who fills all conditions of sub_category_value_id. Now it is returning all the conditions.
I am new to database and don't know much about queries.
Below query will give you distinct products with product_id and product_name on basis of given vendor_id, category_id, subcategory_id's and subcategory_value_id's.
Let me know if this works for you!
SELECT
DISTINCT p.product_id,
p.product_name
FROM products AS p
LEFT JOIN product_category AS pc ON p.product_id = pc.product_id
LEFT JOIN vendor_products AS vp ON p.product_id = vp.product_id
LEFT JOIN subcategories AS sc ON sc.subcategory_id = pc.subcategory_id
LEFT JOIN subcategories_value AS scv ON scv.subcategory_value_id = pc.subcategory_value_id
WHERE vp.vendor_id = 2
AND vp.category_id = 2
AND pc.subcategory_id IN (1, 2)
AND scv.subcategory_value_id IN (1, 4)
ORDER BY p.product_id;
It seems like you shouldn't use left join to product_category table. The LEFT JOIN keyword returns all records from the left table (product_category) Please try like below:
SELECT
p.product_id,
p.product_name,
p.product_photo,
p.size,
p.price,
p.status,
p.product_image_path
FROM
products AS p
INNER JOIN
product_category AS pc
ON
p.product_id = pc.product_id
LEFT JOIN
vendor_products AS vp
ON
vp.product_id = pc.product_id
WHERE
pc.category_id = 2
AND
vp.vendor_id = 36
AND
pc.subcategory_id IN (1,2)
AND
pc.subcategory_value_id IN (1,4)
You want group by and having. It is a little unclear what you mean by "all conditions", but it would look something like this:
SELECT p.*
FROM products p JOIN
product_category pc
ON p.product_id = pc.product_id JOIN
vendor_products AS vp
ON vp.product_id = pc.product_id
WHERE pc.category_id = 2 AND
vp.vendor_id = 36 AND
(pc.subcategory_id, pc.subcategory_value_id) IN ( (1, 1), (2, 4) )
GROUP BY p.product_id -- this is okay because it is presumably the primary key
HAVING COUNT(DISTINCT pc.subcategory_id) = 2;
Notes:
The WHERE clause turns the LEFT JOIN into an INNER JOIN, so use the right JOIN.
I assume you want pairs of values from the subcategory table.
The HAVING clause insists on both subcatgories matching.

Optimize mysql query using various join and order by rand()

I was having trouble on my site, so I went look into mysql slow query log.
Fixed some indexing and also querys without joins now the server load got lower and its running fine.
I still have a query that I havent been able to fix, if any of you have a tip so I can make it better, I would appreciated it.
This is the query
SELECT p.product_id,
p.product_offer_price,
ps.subcategory_name,
pb.brand_name,
pm.model_name,
pm.display_name,
pm.year_from,
pm.year_to
FROM product p
INNER JOIN product_subcategory ps ON ps.subcategory_id = p.product_subcategory_id AND ps.subcategory_category_id = 12
INNER JOIN product_stock pq ON pq.product_id = p.product_id AND pq.product_quantity > 0
INNER JOIN product_photos pp ON pp.product_id = p.product_id
INNER JOIN product_brand pb ON pb.brand_id = p.product_brand_id
INNER JOIN product_model pm ON pm.model_id = p.product_model_id
GROUP BY p.product_id
ORDER BY RAND() LIMIT 4;
This is what explain shows about the query
I was trying to accomplish something like this, but doesn't work
SELECT p.product_id, p.product_offer_price, ps.subcategory_name, pb.brand_name, pm.model_name, pm.display_name, pm.year_from, pm.year_to
FROM product p
INNER JOIN product_subcategory ps ON ps.subcategory_id = p.product_subcategory_id
AND ps.subcategory_category_id =12
INNER JOIN product_stock pq ON pq.product_id = p.product_id
AND pq.product_quantity >0
INNER JOIN product_photos pp ON pp.product_id = p.product_id
INNER JOIN product_brand pb ON pb.brand_id = p.product_brand_id
INNER JOIN product_model pm ON pm.model_id = p.product_model_id
WHERE p.product_id >= FLOOR( 1 + RAND( ) * (
SELECT MAX( product_id )
FROM product ) )
GROUP BY p.product_id
LIMIT 4

Prestashop order products sql

Where I can find Prestashop SQL query where they display the products that were bought in order.
Like this:
I'm creating a custom page that shows 100 orders in table. and if clicked on order its shows the products that were ordered. I made an sql query:
SELECT product_id, product_reference AS kood,product_name AS nimetus,product_quantity AS nr, pl.link_rewrite,psa.quantity as kogukogus,group_concat(ps.product_supplier_reference) as supp_ref, p.location AS asukoht,
CONCAT(c.link_rewrite,'/',p.id_product,'-',pl.link_rewrite,'.html') link
FROM ps_order_detail o
LEFT JOIN ps_product_lang pl on o.product_id = pl.id_product
LEFT JOIN ps_product p on p.id_product = pl.id_product
LEFT JOIN ps_stock_available psa on p.id_product = psa.id_product
LEFT JOIN ps_category_lang c on c.id_category = p.id_category_default
LEFT JOIN ps_product_supplier ps on p.id_product = ps.id_product
WHERE pl.id_lang=2 AND c.id_lang=2 AND id_order= '".$q."'
GROUP BY product_id, kood,nimetus,nr,pl.link_rewrite, kogukogus,asukoht, link
But when product has attributes it duplicates products.
In this case iButton has two colors black and red(attributes). In this order only one black iButton was bought with quantity of 20, but It shows three rows.
I tried to fix this, but that arised another problems with my sql query, that when it has no attribute it dosen't show anything.
SELECT product_id, product_reference AS kood,product_name AS nimetus,product_quantity AS nr, pl.link_rewrite,psa.quantity as kogukogus,group_concat(ps.product_supplier_reference) as supp_ref, p.location AS asukoht,
CONCAT(c.link_rewrite,'/',p.id_product,'-',pl.link_rewrite,'.html') link
FROM ps_order_detail o
JOIN ps_product_lang pl on o.product_id = pl.id_product
JOIN ps_product p on p.id_product = pl.id_product
JOIN ps_stock_available psa on p.id_product = psa.id_product
JOIN ps_category_lang c on c.id_category = p.id_category_default
JOIN ps_product_supplier ps on p.id_product = ps.id_product
LEFT JOIN ps_product_attribute pa on p.id_product=pa.id_product
WHERE pl.id_lang=2 AND pa.id_product_attribute = psa.id_product_attribute AND pa.id_product_attribute =o.product_attribute_id AND c.id_lang=2 AND id_order= '".$q."'
GROUP BY product_id, kood,nimetus,nr,pl.link_rewrite, kogukogus,asukoht, link
How can I fix this problem?
I think that you have to move 2 of your WHERE conditions to the JOIN conditions. Probably it is enough to move only the condition on the LEFT JOIN.
This should be the result:
SELECT DISTINCT product_id, product_reference AS kood,product_name AS nimetus,product_quantity AS nr, pl.link_rewrite,psa.quantity as kogukogus,group_concat(ps.product_supplier_reference) as supp_ref, p.location AS asukoht,
CONCAT(c.link_rewrite,'/',p.id_product,'-',pl.link_rewrite,'.html') link
FROM ps_order_detail o
JOIN ps_product_lang pl on o.product_id = pl.id_product
JOIN ps_product p on p.id_product = pl.id_product
JOIN ps_stock_available psa on p.id_product = psa.id_product
JOIN ps_category_lang c on c.id_category = p.id_category_default
JOIN ps_product_supplier ps on p.id_product = ps.id_product
LEFT JOIN ps_product_attribute pa on p.id_product=pa.id_product
AND psa.id_product_attribute = pa.id_product_attribute
WHERE pl.id_lang=2 AND c.id_lang=2 AND id_order= '".$q."'
Use SELECT DISTINCT instead simple SELECT in your query if you aren't interesting about particular product attributes for your result
Thanks for your answers, this is really silly but when removing kogukogus from group by and result as this:
SELECT product_id, product_reference AS kood,product_name AS nimetus,product_quantity AS nr, pl.link_rewrite,psa.quantity as kogukogus,group_concat(ps.product_supplier_reference) as supp_ref, p.location AS asukoht,
CONCAT(c.link_rewrite,'/',p.id_product,'-',pl.link_rewrite,'.html') link
FROM ps_order_detail o
LEFT JOIN ps_product_lang pl on o.product_id = pl.id_product
LEFT JOIN ps_product p on p.id_product = pl.id_product
LEFT JOIN ps_stock_available psa on p.id_product = psa.id_product
LEFT JOIN ps_category_lang c on c.id_category = p.id_category_default
LEFT JOIN ps_product_supplier ps on p.id_product = ps.id_product
WHERE pl.id_lang=2 AND c.id_lang=2 AND id_order= '".$q."'
GROUP BY product_id, kood,nimetus,nr,pl.link_rewrite,asukoht, link
I got it working somehow. Thanks you #kiks73, Your code didn't work, BUT when I was trying to add group by to you're code, I realized that the problem was with group by. So the bounty goes to you since no one answered anything serious