問題: option_value_id が 1 と 3 の両方を持つ商品を選択したいのですが、ご覧のとおり、option_value_id が 1 つしかない商品も表示されます。
IN の代わりに AND を追加しようとしましたが、明らかに結果が表示されません。
答えは簡単かもしれませんが、現時点ではわかりません。誰か助けてくれませんか?ちょっとしたヒントでも構いません。
これはRelation Divisionと呼ばれ、これを行う 1 つの方法を次に示します。
SELECT *
FROM TABLEName
WHERE Product_ID IN(SELECT Product_ID
FROM Tablename
WHERE option_value_id IN(1, 3)
GROUP BY Product_ID
HAVING COUNT(option_value_id) = 2);
これにより、次のことが得られます。
| ID | PRODUCT_ID | OPTION_VALUE_ID |
-------------------------------------
| 1 | 1 | 1 |
| 3 | 1 | 3 |
| 13 | 2 | 3 |
| 14 | 2 | 1 |
これは物事をセットとして見る例です。最善のアプローチは、SQL の集計、特に having 句を使用することだと思います。MySQL 構文では、これは次のようになります。
select pa.product_id
from Product_Attributes pa
group by pa.product_id
having max(pa.option_value_id = 1) = 1 and
max(pa.option_value_id = 3) = 1
これは関係分割と呼ばれる一般的な問題であり、SO にはそのためのタグもあります: sql-match-all
通常、 には一意の制約がある(product_id, option_value_id)
ため、1 つの解決策は 2 つの結合を使用することです (N 個の属性をチェックする場合は N 個の結合)。
SELECT p.* -- whatever columns you need
FROM product AS p -- from the `product` table
JOIN products_attributes AS pa1
ON pa1.option_value_id = 1
AND pa1.product_id = p.product_id
JOIN products_attributes AS pa2
ON pa2.option_value_id = 3
AND pa2.product_id = p.product_id ;
同様の質問があり、同じ結果 (および Postgres のベンチマーク) を達成するための 10 以上の異なる方法があります: How to filter SQL results in a has-many-through relationship