Reputation: 152
I'm trying to create a SELECT query to get products by some filters. You can see DB structure on the screen below.
definitions
- products types, features
- products features (e.g. price, size, color), significations
- value on some feature, objects
- avalible products on site, trans_obj2sign
- auxiliary table to make many to many relations.
I'm creating query using php considering selected filters:
SELECT o.id, o.name, o.url, GROUP_CONCAT(f.name separator '--|||--') as feature_name, GROUP_CONCAT(f.title separator '--|||--') as feature_title, GROUP_CONCAT(s.value separator '--|||--') as signification_value
FROM objects as o
JOIN trans_obj2sign o2s ON o.id=o2s.object_id
JOIN features f ON o2s.feature_id=f.id
JOIN significations s ON o2s.signification_id=s.id
WHERE o.id IN (
SELECT o2s.object_id
FROM trans_obj2sign o2s
JOIN significations s ON ( o2s.signification_id = s.id )
WHERE (
(s.id IN ("2", "43", "48", "55") AND s.feature =13)
OR (s.id IN ("14", "23", "49", "52") AND s.feature =14)
OR (s.value BETWEEN 0 AND 500 AND s.feature =17)
)
GROUP BY o2s.object_id
HAVING COUNT( o2s.object_id ) =3
)
GROUP BY o.id
LIMIT 0, 50
Inner query returns ids of objects which significations approach to all filters. Main query returns products attributes that are needed.
The questions are:
WHERE s.feature=17 ORDER BY s.value
(pretend that s.feature=17 is product price)Upvotes: 0
Views: 1796
Reputation: 57381
Get rid of the IN+subquery. Just move it to the FROM section to be executed just once.
Like this
SELECT o.id, o.name, o.url, GROUP_CONCAT(f.name separator '--|||--') as feature_name, GROUP_CONCAT(f.title separator '--|||--') as feature_title, GROUP_CONCAT(s.value separator '--|||--') as signification_value
FROM objects as o
JOIN trans_obj2sign o2s ON o.id=o2s.object_id
JOIN features f ON o2s.feature_id=f.id
JOIN significations s ON o2s.signification_id=s.id
JOIN (
SELECT o2s.object_id
FROM trans_obj2sign o2s
JOIN significations s ON ( o2s.signification_id = s.id )
WHERE (
(s.id IN ("2", "43", "48", "55") AND s.feature =13)
OR (s.id IN ("14", "23", "49", "52") AND s.feature =14)
OR (s.value BETWEEN 0 AND 500 AND s.feature =17)
)
GROUP BY o2s.object_id
HAVING COUNT( o2s.object_id ) =3
) filtered on filtered.id=o.id
GROUP BY o.id
LIMIT 0, 50
Add indexes for fields which are used in WHERE.
To add ORDER BY
place the query in a FROM section (as subquery) and use ORDER BY
Upvotes: 1