SELECT *
FROM articles
LEFT JOIN categories ON categories.id = articles.category_id
WHERE categories.id = (
SELECT id
FROM categories
WHERE slug = 'portfolio'
)
OR categories.parent_id = (
SELECT id
FROM categories
WHERE slug = 'portfolio'
)
How can I make this sub select more efficient? Im basically getting the id of portfolio and matching that but it may perform 2 sub selects. Is there a more efficient way?
There is no need to have subselects at all in this query! The 1st subselect can be turned straight into a plain where criterion: categories.slug = 'portfolio'
. To replace the 2nd subselect you need to join the categories table once more to get the parent category and filter in the where clause.
You can also consider rewriting this as a union to optimise index usage.
SELECT articles.*, categories.* FROM articles LEFT JOIN categories ON categories.id = articles.category_id
WHERE categories.slug = 'portfolio'
UNION DISTINCT
SELECT articles.*, c1.* FROM articles LEFT JOIN categories c1 ON c1.id = articles.category_id
LEFT JOIN categories c2 ON c2.id=c1.parent_id
WHERE c2.slug = 'portfolio'
You can solve this by joining the category table again as the parent:
SELECT * FROM articles
LEFT JOIN categories
ON categories.id = articles.category_id
LEFT JOIN categories parent
ON parent.id = categories.parent_id
WHERE categories.slug = 'portfolio'
or parent.slug = 'portfolio'
The sub selects are removed entirely.
Another method for removing the duplicate sub selection would be using a table expression:
WITH cat AS
(
SELECT id
FROM categories
WHERE slug = 'portfolio'
)
SELECT *
FROM articles
JOIN categories
ON categories.id = articles.category_id
JOIN cat
ON cat.id = categories.id
OR cat.id = categories.parent_id
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.