Reputation: 408
I have query that work fine, but it has 2 the same subqueries
SELECT *,
(SELECT count(O.id) FROM `offer` O WHERE O.product_id = P.id) AS poffers
FROM `product` P
JOIN product_section PS ON (PS.product_id = P.id AND PS.section_id IN (14))
WHERE P.deleted is NULL
AND (SELECT count(O.id) FROM `offer` O WHERE O.product_id = P.id) > 0
I try to optimize with JOIN, but new query returns empty result
SELECT *, OJ.pcount AS poffers
FROM `product` P
JOIN product_section PS ON PS.product_id = P.id AND PS.section_id IN (14)
JOIN (SELECT count(O.id) AS pcount, O.product_id FROM `offer` O )
AS OJ ON OJ.product_id = P.id
WHERE P.deleted is NULL AND OJ.pcount > 0
Than i try variables, but i think i use it wrong, query returns empty result
SELECT *,
@o := (SELECT count(O.id) FROM `offer` O WHERE O.product_id = P.id)
AS poffers
FROM `product` P
JOIN product_section PS ON (PS.product_id = P.id AND PS.section_id IN (14))
WHERE P.deleted is NULL
AND @o > 0
Upvotes: 0
Views: 122
Reputation: 60858
Avoid the dependent subqueries. Instead, have one query which relates products to offer counts. This query you can use in several places. It will most likely be stored temporarily in memory, avoiding duplicate computations, but the database engine might do more clever things as well.
SELECT *, O.cnt AS poffers
FROM product P
JOIN product_section PS ON (PS.product_id = P.id AND PS.section_id IN (14))
JOIN (SELECT product_id, count(id) AS cnt
FROM offer
GROUP BY product_id
) O ON (O.product_id = P.id)
WHERE P.deleted is NULL AND O.cnt > 0
If the relation between P and PS is one-to-one, then you could even work without any subquerys whatsoever:
SELECT *, COUNT(O.id) AS poffers
FROM product P
JOIN product_section PS ON (PS.product_id = P.id AND PS.section_id IN (14))
JOIN offer O ON (O.product_id = P.id)
WHERE P.deleted is NULL
GROUP BY P.id
You also should consider whether there is a good reason to count a specific column. In most cases, COUNT(*)
will be faster than COUNT(col)
. The only reason to use the latter is if you explicitely want to exclude NULL
values from the count.
Upvotes: 1
Reputation: 54016
give it a try ( not tested )
SELECT P.*,PS.*,count(O.id) AS oCount
FROM `product` P
INNER JOIN `product_section` PS ON (PS.product_id = P.id)
INNER JOIN `offer` O ON (O.product_id = P.id)
WHERE P.deleted is NULL AND PS.section_id =14
GROUP BY O.product_id
HAVING oCount> 0
more optimized
SELECT P.*,PS.*,count(O.id) AS oCount
FROM `product` P
INNER JOIN (`product_section` PS,`offer` O) ON
(PS.product_id = P.id AND O.product_id = P.id)
WHERE P.deleted is NULL AND PS.section_id =14
GROUP BY O.product_id
HAVING oCount> 0
TIPS:
*
, instead write only those column names which you want to retrieve ON
& WHERE
conditionUpvotes: 1