Get count from select - mysql

my sql code is
select pr.category_id FROM products p
LEFT JOIN products_category_rel pr ON p.id = pr.product_id
left JOIN products_design pd ON p.id = pd.product_id
LEFT JOIN products_producer pp ON pp.id = p.producer_id
group by pr.category_id, p.id
sql return array [1436, 1436, ..., 1436, 1437,...,1437] where the value 1436 is in the array 150 times and 1437 is 100 times
I need retrun columns -> 1436 | 150 , 1437 | 100
can you help me?

Try this:
select pr.category_id, COUNT(pr.category_id) AS category_count
FROM products p
LEFT JOIN products_category_rel pr ON p.id = pr.product_id
left JOIN products_design pd ON p.id = pd.product_id
LEFT JOIN products_producer pp ON pp.id = p.producer_id
group by pr.category_id
order by pr.category_id;

Related

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'

Getting parent categories sum(price) formed in different tables

I am trying to get the total prices of all parent categories in a specific month and year. A parent category is any category with a parent_id == 0. My query is like below:
SELECT
ROUND(SUM(od.total_price)) as price,
c.parent_id as pId,
c1.name
FROM a_orders o
INNER JOIN a_order_details as od on o.id = od.order_id
INNER JOIN a_product as p on p.id = od.product_id
INNER JOIN a_category as c on c.id = p.category_id
LEFT OUTER JOIN a_category c1 ON c.parent_id = c1.id
WHERE YEAR(order_date) = 2018
AND o.STAT = 'Y'
AND MONTH(order_date) = 6
GROUP BY c.parent_id;
I'm getting parent categories just which have a price but I need to get all parent categories, if there is no price result should be 0.
My sqlfiddle is -> http://sqlfiddle.com/#!9/b9f4c1/1
My result is like this :
price pId name
410 1 T-SHIRT
400 2 JEANS
But should be like this :
price pId name
410 1 T-SHIRT
400 2 JEANS
0 6 SHOES
To do this you need switch your logic around. First select all of your parent categories, then join your order data. This way you can ensure all of the desired categories will be included in the results.
There are a bunch of ways you could approach this — here I created a subquery with all of the order data and then a LEFT JOIN with the category table:
SELECT
IFNULL(ROUND(SUM(orders.total_price)),0) AS price,
c.id AS pId,
c.name
FROM a_category c
LEFT JOIN (
SELECT od.total_price, c.parent_id
FROM a_orders o
INNER JOIN a_order_details od ON o.id = od.order_id
INNER JOIN a_product p ON p.id = od.product_id
INNER JOIN a_category c ON c.id = p.category_id
WHERE YEAR(order_date) = 2018
AND o.STAT = 'Y'
AND MONTH(order_date) = 6
) orders ON orders.parent_id = c.id
WHERE c.parent_id = 0
GROUP BY c.id;
http://sqlfiddle.com/#!9/b9f4c1/3

Is a way to optimize big mysql query?

This is my query and it's to slow... I'm looking for the way to optimize it.
SELECT p.id,
Group_concat(pc.cat_id) AS groups,
p.code,
p.NAME,
p.price,
p.thumbnail,
p.image,
mc.queries AS merch_queries,
mc.position AS merch_position,
Group_concat(op.image) AS option_images,
cf_RETAIL.value AS custom_RETAIL,
cf_rating.value AS custom_rating,
cf_reviews.value AS custom_reviews,
cf_sku.value AS custom_sku,
cf_brand.value AS custom_brand,
cf_custom_thumbnail.value AS custom_custom_thumbnail
FROM s01_products AS p
LEFT JOIN s01_categoryxproduct AS pc
ON p.id = pc.product_id
LEFT JOIN (SELECT pv.product_id,
pv.value
FROM s01_cfm_prodfields AS pf
INNER JOIN s01_cfm_prodvalues AS pv
ON pf.id = pv.field_id
WHERE pf.code = 'RETAIL') AS cf_RETAIL
ON p.id = cf_RETAIL.product_id
LEFT JOIN (SELECT pv.product_id,
pv.value
FROM s01_cfm_prodfields AS pf
INNER JOIN s01_cfm_prodvalues AS pv
ON pf.id = pv.field_id
WHERE pf.code = 'rating') AS cf_rating
ON p.id = cf_rating.product_id
LEFT JOIN (SELECT pv.product_id,
pv.value
FROM s01_cfm_prodfields AS pf
INNER JOIN s01_cfm_prodvalues AS pv
ON pf.id = pv.field_id
WHERE pf.code = 'reviews') AS cf_reviews
ON p.id = cf_reviews.product_id
LEFT JOIN (SELECT pv.product_id,
pv.value
FROM s01_cfm_prodfields AS pf
INNER JOIN s01_cfm_prodvalues AS pv
ON pf.id = pv.field_id
WHERE pf.code = 'sku') AS cf_sku
ON p.id = cf_sku.product_id
LEFT JOIN (SELECT pv.product_id,
pv.value
FROM s01_cfm_prodfields AS pf
INNER JOIN s01_cfm_prodvalues AS pv
ON pf.id = pv.field_id
WHERE pf.code = 'brand') AS cf_brand
ON p.id = cf_brand.product_id
LEFT JOIN (SELECT pv.product_id,
pv.value
FROM s01_cfm_prodfields AS pf
INNER JOIN s01_cfm_prodvalues AS pv
ON pf.id = pv.field_id
WHERE pf.code = 'custom_thumbnail') AS cf_custom_thumbnail
ON p.id = cf_custom_thumbnail.product_id
LEFT JOIN (SELECT p.product_id AS product_id,
Group_concat(q.query) AS queries,
Min(p.position) AS position
FROM s01_srch_merchandisingproduct AS p
LEFT JOIN s01_srch_merchandisingquery AS q
ON q.id = p.query_id
GROUP BY p.product_id) AS mc
ON p.id = mc.product_id
LEFT JOIN s01_options AS op
ON p.id = op.product_id
AND op.image <> ''
WHERE p.active = 1
GROUP BY p.id
Thanks for any help!
Updated Tables Schema:
**s01_categoryxproduct**
cat_id,
product_id,
disp_order
**s01_products**
id
catcount
agrpcount
pgrpcount
disp_order
code
name
thumbnail
image
price
cost
descrip
weight
taxable
active
sku
cancat_id
page_id
page_title
dt_created
dt_updated
**s01_CFM_ProdValues**
field_id,
product_id,
value,
value_long
**s01_CFM_ProdFields**
id,
code,
name,
group_id,
fieldtype,
info,
facet
**s01_Options**
id,
product_id,
attr_id,
disp_order,
code,
prompt,
price,
cost,
weight,
image
**s01_SRCH_MerchandisingProduct**
id,
product_id,
query_id,
position
**s01_SRCH_MerchandisingQuery**
id,
query
"Over-normalization" and EAV are the problems.
Put prodfields and prodvalues in the same table. Splitting them into two tables leads to performance-eating overhead.
More on optimizing an EAV table: http://mysql.rjweb.org/doc.php/index_cookbook_mysql#speeding_up_wp_postmeta
More discussion of why EAV is bad: http://mysql.rjweb.org/doc.php/eav
SELECT p.id,
Group_concat(pc.cat_id) AS groups,
p.code,
p.NAME,
p.price,
p.thumbnail,
p.image,
mc.queries AS merch_queries,
mc.position AS merch_position,
Group_concat(op.image) AS option_images,
IF(pf.code = 'RETAIL',pv.value , NULL) AS custom_RETAIL,
IF(pf.code = 'rating',pv.value , NULL) AS custom_rating,
IF(pf.code = 'reviews',pv.value , NULL) AS custom_reviews,
IF(pf.code = 'brand',pv.value , NULL) AS custom_brand,
IF(pf.code = 'custom_thumbnail',pv.value , NULL) AS custom_custom_thumbnail,
pvr.value AS custom_rating,
FROM s01_products AS p
LEFT JOIN s01_categoryxproduct AS pc ON p.id = pc.product_id
LEFT JOIN s01_cfm_prodfields AS cf_RETAIL ON p.id = cf_RETAIL.product_id
LEFT JOIN s01_cfm_prodvalues AS pv ON cf_RETAIL.id = pv.field_id
LEFT JOIN (SELECT p.product_id AS product_id,
Group_concat(q.query) AS queries,
Min(p.position) AS position
FROM s01_srch_merchandisingproduct AS p
LEFT JOIN s01_srch_merchandisingquery AS q
ON q.id = p.query_id
GROUP BY p.product_id) AS mc
ON p.id = mc.product_id
LEFT JOIN s01_options AS op
ON p.id = op.product_id
AND op.image <> ''
WHERE p.active = 1
GROUP BY p.id`;

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

Select a product from filters

I have a problem with a query:
I have 3 tables:
products (id, name)
settings (id, name)
product_setting (product_id, setting_id)
for example: I would like to select only the products you have selected filters!
I do this:
SELECT p. *, s.id as setting
FROM Products p
INNER JOIN product_setting p2 ON (p.id = p2.product_id)
INNER JOIN settings s ON (s.id = p2.setting_id)
WHERE s.id IN (1,2)
but I get all products that have the 'setting' id = 1 OR id = 2.
How to get only those products that have those 'setting' (AND)?
thanks!!
SELECT p.*, s.id as setting
FROM Products p
INNER JOIN product_setting p2 ON (p.id = p2.product_id)
INNER JOIN settings s ON (s.id = p2.setting_id)
WHERE s.id IN (1,2)
GROUP BY p.id
HAVING COUNT(*)=2; // size of IN()
This seems like over kill but...
SELECT p. *, s.id as setting
FROM Products p
INNER JOIN product_setting p2 ON (p.id = p2.product_id)
INNER JOIN settings s ON (s.id = p2.setting_id)
INNER JOIN settings s2 ON (s.id = p2.setting_id)
WHERE
s.id = 1
AND s2.id = 2