How write mysql query corresponding this tables - mysql

Hi database professionals. I need your help
This is my database tables
I want to get this result
How can I write select query to get that result ?
I write this query , but it works very slow (20 minute)
SELECT c.name, p.title, tbl1.count, tbl1.sum,tbl2.count_1, tbl2.sum_1, tbl3.count_2, tbl3.sum_2
FROM `client` c LEFT JOIN
(SELECT c.name, p.id, p.title,p.unit, o.client_id, COUNT(*) AS `count`, SUM(op.price) AS `sum`
FROM `order` o INNER JOIN order_product op ON o.id = op.order_id
INNER JOIN product p ON op.product_id = p.id
INNER JOIN `client` c ON c.id = o.client_id
WHERE MONTH(o.date) = MONTH('2013-07-01') AND YEAR(o.date) = YEAR('2013-07-01') AND p.category_id = 1
GROUP BY c.id, p.id, YEAR(o.date), MONTH(o.date)) AS tbl1 ON c.id = tbl1.client_id
LEFT JOIN
(SELECT p.id, p.title,p.unit, c.name, o.client_id, COUNT(*) AS `count_1`, SUM(op.price) AS `sum_1`
FROM `order` o INNER JOIN order_product op ON o.id = op.order_id
INNER JOIN product p ON op.product_id = p.id
INNER JOIN `client` c ON c.id = o.client_id
WHERE MONTH(o.date) = MONTH(DATE_ADD('2013-07-01', INTERVAL 1 MONTH)) AND
YEAR(o.date) = YEAR(DATE_ADD('2013-07-01', INTERVAL 1 MONTH)) AND p.category_id = 1
GROUP BY c.id, p.id, YEAR(o.date), MONTH(o.date)) AS tbl2 ON c.id = tbl2.client_id
LEFT JOIN
(SELECT p.id, p.title,p.unit, c.name, o.client_id, COUNT(*) AS `count_2`, SUM(op.price) AS `sum_2`
FROM `order` o INNER JOIN order_product op ON o.id = op.order_id
INNER JOIN product p ON op.product_id = p.id
INNER JOIN `client` c ON c.id = o.client_id
WHERE MONTH(o.date) = MONTH(DATE_ADD('2013-07-01', INTERVAL 2 MONTH)) AND
YEAR(o.date) = YEAR(DATE_ADD('2013-07-01', INTERVAL 2 MONTH)) AND p.category_id = 1
GROUP BY c.id, p.id, YEAR(o.date), MONTH(o.date)) AS tbl3 ON c.id = tbl3.client_id
, product p
WHERE (tbl1.id = p.id OR tbl2.id = p.id OR tbl3.id = p.id)
ORDER BY c.name

Related

How to do GROUP BY and COUNT(*) in JOIN MySQL

I have tables named company, product, purchase_order, skid, process_record and I want MySQL query result as below.
I tried
SELECT s.id as skidId, s.skidBarcode, po.poNumber, s.companyId, c.companyName, p.productId , p.productName, totalProcessed
FROM skid s
INNER JOIN company c ON s.companyId = c.id
INNER JOIN purchase_order po on s.purchaseOrderId = po.id
INNER JOIN product prdct on p.productId = prdct.id
LEFT JOIN (SELECT skidID, productId , COUNT(*) as processedQuantity FROM process_record GROUP BY productId ) p ON p.skidID= s.id
WHERE s.status = 'closed' ORDER By s.companyId,s.id
However, this query result gives processedQuantity count NULL and random wrong count on some rows.
How can I get the desired MySQL query output as shown in screenshot?
I added GROUP BY skidID, productId instead of GROUP BY productId and it resolved the issue.
SELECT s.id as skidId, s.skidBarcode, po.poNumber, s.companyId, c.companyName, p.productId , p.productName, totalProcessed
FROM skid s
LEFT JOIN (SELECT skidID, productId , COUNT(*) as processedQuantity FROM process_record GROUP BY skidID, productId ) p ON p.skidID= s.id
INNER JOIN company c ON s.companyId = c.id
INNER JOIN purchase_order po on s.purchaseOrderId = po.id
INNER JOIN product prdct on p.productId = prdct.id
WHERE s.status = 'closed' ORDER By s.companyId,s.id

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`;

MYSQL combining two counts that use same columns

I have two queries that i need to combine into one query. The problem is they are using the same columns in where clause depending on what i need to fetch.
Query 1
SELECT c.fullname, COUNT( DISTINCT sst.id ) AS 'Liczba rozpoczetych szkolen'
FROM mdl_course c
INNER JOIN mdl_scorm s ON s.course = c.id
INNER JOIN mdl_scorm_scoes_track sst ON s.id = sst.scormid
INNER JOIN mdl_user u ON u.id = sst.userid
WHERE sst.element = 'x.start.time' AND u.deleted =0
GROUP BY c.fullname ORDER BY `Liczba rozpoczetych szkolen` ASC
Query 2
SELECT c.fullname, COUNT(DISTINCT sst.userid ) AS 'Liczba_ukonczonych_szkolen'
FROM mdl_course c
INNER JOIN mdl_scorm s ON s.course=c.id
INNER JOIN mdl_scorm_scoes_track sst ON s.id = sst.scormid
INNER JOIN mdl_user u ON sst.userid=u.id
where `element`='cmi.core.score.raw' and `value` = 100 and u.deleted = 0
GROUP BY c.fullname ORDER BY `Liczba_ukonczonych_szkolen` DESC
They are depending on the same column named 'element'.
How i can display the result as
fullname Liczba rozpoczetych szkolen Liczba_ukonczonych_szkolen
A1 34 4
A2 5 3
A3 34 33
I've came up with this one, whitch works. Thanks for advice #HoneyBadger
SELECT t1.fullname, t1.Liczba_rozpoczetych_szkolen, t2.Liczba_ukonczonych_szkolen,
round(((t2.Liczba_ukonczonych_szkolen /t1.Liczba_rozpoczetych_szkolen)*100),2) as procentowo
FROM
(SELECT c.fullname, COUNT( DISTINCT sst.id ) AS Liczba_rozpoczetych_szkolen
FROM mdl_course c
INNER JOIN mdl_scorm s ON s.course = c.id
INNER JOIN mdl_scorm_scoes_track sst ON s.id = sst.scormid
INNER JOIN mdl_user u ON u.id = sst.userid
WHERE sst.element = 'x.start.time' AND u.deleted =0
GROUP BY c.fullname ) AS t1,
(SELECT c.fullname, COUNT(DISTINCT sst.userid ) AS Liczba_ukonczonych_szkolen
FROM mdl_course c
INNER JOIN mdl_scorm s ON s.course=c.id
INNER JOIN mdl_scorm_scoes_track sst ON s.id = sst.scormid
left join mdl_user u ON sst.userid=u.id
where `element`='cmi.core.score.raw' and `value` = 100 and u.deleted = 0
GROUP BY c.fullname) as t2
WHERE t1.fullname = t2.fullname
You can join them together like this:
SELECT COALESCE(R.fullname, U.fullname) AS fullname
, COALESCE(R.Liczba_rozpoczetych_szkolen, 0) AS Liczba_rozpoczetych_szkolen
, COALESCE(R.Liczba_ukonczonych_szkolen, 0) AS Liczba_ukonczonych_szkolen
FROM (
SELECT c.fullname
, COUNT( DISTINCT sst.id ) AS Liczba_rozpoczetych_szkolen
FROM mdl_course c
INNER JOIN mdl_scorm s
ON s.course = c.id
INNER JOIN mdl_scorm_scoes_track sst
ON s.id = sst.scormid
INNER JOIN mdl_user u
ON u.id = sst.userid
WHERE sst.element = 'x.start.time'
AND u.deleted =0
GROUP BY c.fullname
) AS R
FULL JOIN (
SELECT c.fullname
, COUNT(DISTINCT sst.userid ) AS Liczba_ukonczonych_szkolen
FROM mdl_course c
INNER JOIN mdl_scorm s
ON s.course=c.id
INNER JOIN mdl_scorm_scoes_track sst
ON s.id = sst.scormid
INNER JOIN mdl_user u
ON sst.userid=u.id
where `element`='cmi.core.score.raw'
AND `value` = 100
AND u.deleted = 0
GROUP BY c.fullname
) AS U
ON R.fullname = U.fullname
Try the query with the ORed predicates and extra filtering with CASE in the SELECT list. Kind of
SELECT c.fullname, COUNT(DISTINCT CASE WHEN sst.element = 'x.start.time' THEN sst.id END) AS 'Liczba rozpoczetych szkolen'
, COUNT(DISTINCT CASE WHEN sst.element = 'cmi.core.score.raw' and `value` = 100 THEN sst.userid END) AS 'Liczba_ukonczonych_szkolen'
FROM mdl_course c
INNER JOIN mdl_scorm s ON s.course = c.id
INNER JOIN mdl_scorm_scoes_track sst ON s.id = sst.scormid
INNER JOIN mdl_user u ON u.id = sst.userid
WHERE sst.element = IN( 'x.start.time', 'cmi.core.score.raw') AND u.deleted =0
GROUP BY c.fullname ORDER BY `Liczba rozpoczetych szkolen` ASC

Unable to count the number of rows returned from query

I have this query
MYSQL:
SELECT COUNT(op.quantity) AS quantity_sold, op.model AS model_number,
op.name AS product_name, ptc.category_id, cd.name
FROM ((`order_product` op INNER JOIN `product` p ON op.product_id = p.product_id)
INNER JOIN (`product_to_category` ptc
INNER JOIN `category_description` cd ON ptc.category_id = cd.category_id) ON op.product_id = ptc.product_id)
INNER JOIN `order` o on o.order_id = op.order_id GROUP BY op.model ORDER BY quantity_sold DESC;
I tried this code to count the no. of rows for the above result.
SELECT COUNT(*) AS total FROM ((`order_product` op INNER JOIN `product` p ON op.product_id = p.product_id)
INNER JOIN (`product_to_category` ptc
INNER JOIN `category_description` cd ON ptc.category_id = cd.category_id) ON op.product_id = ptc.product_id)
INNER JOIN `order` o on o.order_id = op.order_id GROUP BY op.model;
But I am unable to get the count single value.
I need the count of rows returned from the first query as a single value for the purpose of pagination.
If you want the row count that your query returns, wrapping it in an outer query should give you what you want:
SELECT COUNT(*) AS row_count FROM (
SELECT
COUNT(op.quantity) AS quantity_sold,
op.model AS model_number,
op.name AS product_name,
ptc.category_id,
cd.name
FROM order_product op
INNER JOIN product p ON op.product_id = p.product_id
INNER JOIN product_to_category ptc ON op.product_id = ptc.product_id
INNER JOIN category_description cd ON ptc.category_id = cd.category_id
INNER JOIN `order` o on o.order_id = op.order_id
GROUP BY op.model
ORDER BY quantity_sold DESC
) A;

Multiple inner joins to get a complex report, not working

For the schema below, I need to get this report
This is what I have
select c.name, sr.name, count(o.order_id)
from contact c
INNER JOIN accounts a
ON c.account_id=a.account_id
INNER JOIN sales_reps sr
ON a.sales_rep_id =sr.sales_rep_id
INNER JOIN orders o
ON a.account_id =o.account_id
where o.order_id in (
select SUM(oi.quantity*p.price) from
order_items oi INNER JOIN parts p
on oi.part_id =p.part_id
)
group by a.account_id, c.name
But this does not give any results.
Please help.
Your where condition is not right, how should be a order_id equal a sum?
Try the below:
select
c.name, sr.name, COUNT(o.order_id), SUM(op.order_total)
FROM
contact c
INNER JOIN
accounts a ON c.account_id = a.account_id
INNER JOIN
sales_reps sr ON a.sales_rep_id = sr.sales_rep_id
INNER JOIN
orders o ON a.account_id = o.account_id
INNER JOIN
(SELECT
oi.order_id, SUM(oi.quantity * p.price) AS order_total
FROM
order_items oi
INNER JOIN
parts p ON oi.part_id = p.part_id
GROUP BY
oi.order_id
) op ON o.order_id = op.order_id
WHERE o.delivery_data >= CURDATE()
GROUP by c.contact_id
It won't give results as your WHERE ... IN SELECT is based on a query returning a sum() value which will not equal a key (most likely), or incorrect at best... and since you are dealing with a quantity and price which will have decimal precision (typically), you won't even get that to match even LESS likely...
I would swap the query around to pre-qualify the orders within a given date in question and sum that... THEN join to rest...
select
c.name,
sr.name,
PreQualified.NumberOrders,
PreQualified.OrderTotal
from
( select
o.Account_ID,
count( distinct o.order_id ) as NumberOrders,
sum( oi.quantity * p.price ) as OrderTotal
from
orders o
join order_items oi
on o.order_id = oi.order_id
join parts p
on oi.part_id = p.part_id
where
o.Delivery_Date >= CURDATE()
group by
o.Account_ID ) as PreQualified
JOIN Accounts a
on PreQualified.Account_ID = a.Account_ID
Join Contact C
on a.Account_ID = c.Account_ID
JOIN Sales_Reps sr
ON a.sales_rep_id = sr.sales_rep_id
If you want to count records use
count(*)
Instead of
count(o.order_id)