I am attempting to do a tag system for selecting products from a database. I have read that the best way to achieve this is via a many-to-many relationship as using LIKE \'%tag%
No need to do multiple joins. If you need to match all tags, you can use an IN
clause with a subquery like this:
select p.sku, p.name, p.path
from shop_products p
where p.sku in (
select pc.product_sku
from shop_products_categories pc
inner join shop_categories c on pc.category_id = c.id
where c.path in ('flowers', 'romance')
group by pc.product_sku
having count(distinct c.path) = 2
)
Note that you will need to adjust the number 2 to be the number of unique tags you are matching on. Beware in case this is user-entered data and they enter the same tag twice.
SELECT
p.sku, p.name, p.path
FROM
shop_products p
INNER JOIN
(
SELECT A.sku FROM
(
SELECT product_sku sku FROM shop_products_categories
WHERE category_id=(SELECT id FROM shop_categories WHERE path='flowers')
) A
INNER JOIN
(
SELECT product_sku sku FROM shop_products_categories
WHERE category_id=(SELECT id FROM shop_categories WHERE path='romance')
) B
USING (sku)
) flowers_and romance
USING (sku)
;
Make sure you have these indexes:
ALTER TABLE shop_categories ADD INDEX (path,id);
ALTER TABLE shop_categories ADD UNIQUE INDEX (path);
ALTER TABLE shop_products_categories ADD INDEX (product_sku,category_id);