I have a products table. I want to select all fields (of a given row) and the most profitable discount that the user can claim (depends on ordered quantity of the product).
When selecting only one value only, is it more performant to use a JOIN, like this:
SELECT p.*, qd.price AS qd_price
FROM products AS p
-- Find all applicable QDs
LEFT OUTER JOIN quantity_discounts as qd
ON p.id=qd.product_id
AND qd.min_amount <= ?
AND (
(qd.user_id IS NULL OR qd.user_id = 0 OR qd.user_id = ?)
OR (qd.group_id IS NULL OR qd.group_id = 0 OR qd.group_id = ?)
)
WHERE p.id=?
-- Get the lowest QD price
ORDER BY qd.price ASC
LIMIT 1
or a subquery, like this:
SELECT p.*,
(SELECT price FROM quantity_discounts
WHERE product_id=p.id
AND (
(user_id=? or user_id=0 or user_id IS NULL)
OR (group_id=? or group_id=0 or group_id IS NULL)
)
AND qd.min_amount <= ?
ORDER BY price LIMIT 1) AS qd_price
FROM products as p
WHERE p.id=?
Best Answer
The
ORs
are deadly for performance. For starters, decide on0
orNULL
so you won't have to test for both. (That won't actually help any since there would still be otherORs
.)I'm dubious about the formulation of the
LEFT JOIN
. (BTW,OUTER
is optional.) Normally when usingLEFT
, theON
only says how the tables are related (p.id=qd.product_id
); theWHERE
provides the filtering.I don't know which is better, but since you seem to be limiting to one
id
(viaWHERE p.id=?
), then the second formulation will look intoquantity_discounts
only once, and (hopefully) won't have too many rows to check. That is, theOR
may not be as bad as I started out with.A slight help on
quantity_discounts
will beNow I am worried. One formulation has
AND qd.min_amount <= ?
, the other does not.