我有两个通过第三个连接表多对多相关的表:products 和 categories。每个产品可以属于多个类别。这是典型的多对多关系:
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
有用。但它非常慢,以至于我无法在生产中使用它。所有索引都已就位,但此查询会产生 5 个相关子查询,并且表很大。
有没有办法在没有依赖子查询的情况下解决相同的任务或以其他方式优化此查询?
更新
索引是:
products: PRIMARY KEY (id)
categories: PRIMARY KEY (id)
products_to_categories: PRIMARY KEY (product_id, caregory_id)
所有表都是 InnoDB