У меня есть две таблицы, относящиеся ко многим ко многим через третью соединительную таблицу: продукты и категории .Каждый товар может быть в нескольких категориях.Это типичная реализация «многие ко многим»:
products
-------------
id
product_name
categories
-------------
id
category_name
products_to_categories
-------------
product_id
caregory_id
Я хочу разрешить пользователям выполнять поиск продуктов, которые входят в некоторые из выбранных категорий и не входят в другие выбранные категории в то же время.время.
Пример: найти все продукты, которые находятся в категориях "Компьютеры" и "Программное обеспечение", но не в категориях "Игры", "Программирование" и "Образование".
Здесьзапрос, который я разработал для этого:
SELECT product_name
FROM products
WHERE
EXISTS (SELECT product_id FROM products_to_categories WHERE category_id = 1 AND product_id = products.id)
AND EXISTS (SELECT product_id FROM products_to_categories WHERE category_id = 2 AND product_id = products.id)
AND NOT EXISTS (SELECT product_id FROM products_to_categories WHERE category_id = 3 AND product_id = products.id)
AND NOT EXISTS (SELECT product_id FROM products_to_categories WHERE category_id = 4 AND product_id = products.id)
AND NOT EXISTS (SELECT product_id FROM products_to_categories WHERE category_id = 5 AND product_id = products.id)
ORDER BY id
Это работает.Но это так невероятно медленно, что я просто не могу использовать его в производстве.Все idex на месте, но этот запрос приводит к 5 зависимым подзапросам, и таблицы огромны.
Есть ли способ решить ту же задачу без зависимых подзапросов или оптимизировать этот запрос каким-либо другим способом?
ОБНОВЛЕНИЕ
Индексы:
products: PRIMARY KEY (id)
categories: PRIMARY KEY (id)
products_to_categories: PRIMARY KEY (product_id, caregory_id)
Все таблицы InnoDB