My goal is to select articles where the primary_category_id
( articles
table) or any of the secondary categories ( articles_secondary_categories
join table) are a given value. In this example query, category 1. I tried using other types of joins but the caveat here is that an article might not have any secondary categories.
SELECT DISTINCT articles.*
FROM articles
LEFT JOIN articles_secondary_categories AS categories
ON categories.article_id = articles.id
WHERE
(
primary_category_id = 1
OR
categories.category_id = 1
)
AND articles.state = "published"
AND edition_id = 1
ORDER BY publish_at DESC
LIMIT 10;
Any help optimizing this or alternatives are welcome. In a DB with 4k articles
and 7k articles_secondary_categories
(not categories) it takes 5 seconds to run this query.
You can reverse the query on the secondary categories:
(SELECT articles.*
FROM articles
WHERE primary_category_id = 1)
UNION DISTINCT
(SELECT articles.*
FROM articles_secondary_categories AS categories
JOIN articles ON (categories.article_id = articles.id)
WHERE categories.category_id = 1
GROUP BY articles_id)
ORDER BY publish_at DESC
LIMIT 10;
It should give you a decent speed boost - just make sure you index categories.articles_id
Avoid using OR
in your where clause. Optimizers usually don't use indexes with OR
predicates.
Try moving the categories.category_id = 1
into the join condition:
SELECT articles.*
FROM articles
LEFT JOIN articles_secondary_categories AS categories
ON categories.article_id = articles.id and categories.category_id = 1
WHERE 1 in (ifnull(categories.category_id, primary_category_id), primary_category_id)
AND articles.state = "published"
AND edition_id = 1
ORDER BY publish_at DESC
LIMIT 10;
The key to this query is 1 in (ifnull(categories.category_id, primary_category_id), primary_category_id)
, which says "if we got a join to categories, use that in the list, otherwise use the primary_category_id, and in all cases use the primary_category_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.