3番目の接続テーブルを介して多対多に関連する2つのテーブルがあります:製品とカテゴリ。各製品はいくつかのカテゴリに分類できます。これは典型的な多対多の実現です。
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
できます。しかし、それは非常に遅いので、私はそれを本番環境で使用することができません。すべてのidexeが配置されていますが、このクエリでは5つの従属サブクエリが生成され、テーブルは巨大になります。
依存するサブクエリなしで同じタスクを解決したり、他の方法でこのクエリを最適化する方法はありますか?
アップデート
インデックスは次のとおりです。
products: PRIMARY KEY (id)
categories: PRIMARY KEY (id)
products_to_categories: PRIMARY KEY (product_id, caregory_id)
すべてのテーブルはInnoDBです