リレーショナル データベースの性質上、このようなクエリは非常に簡単だと思っていましたが、うまくいっているようです。私も周りを検索しましたが、本当に役立つものは何も見つかりませんでした。状況は次のとおりです。
製品と製品タグの単純な関係があるとします。これは 1 対多の関係であるため、次のようになります。
productid | tag
========================
1 | Car
1 | Black
1 | Ford
2 | Car
2 | Red
2 | Ford
3 | Car
3 | Black
3 | Lexus
4 | Motorcycle
4 | Black
5 | Skateboard
5 | Black
6 | Skateboard
6 | Green
すべてを照会する最も効率的な方法は何(Ford OR Black OR Skateboard) AND NOT (Motorcycles OR Green)
ですか? 実行する必要がある別のクエリは、 all のようなもの(Car) or (Skateboard) or (Green AND Motorcycle) or (Red AND Motorcycle)
です。
products テーブルには約 150k のレコードがあり、tags テーブルには 600k のレコードがあるため、クエリは可能な限り効率的である必要があります。これは私がいじっているクエリの 1 つ (例 #1) ですが、約 4 秒ほどかかるようです。どんな助けでも大歓迎です。
SELECT p.productid
FROM products p
JOIN producttags tag1 USING (productid)
WHERE p.active = 1
AND tag1.tag IN ( 'Ford', 'Black', 'Skatebaord' )
AND p.productid NOT IN (SELECT productid
FROM producttags
WHERE tag IN ( 'Motorcycle', 'Green' ));
アップデート
これまでに見つけた最速のクエリは、次のようなものです。100〜200ミリ秒かかりますが、かなり柔軟性がなく、醜いようです。Ford
基本的に、 、Black
、またはに一致するすべての製品を取得していますSkateboard
。一致した製品のすべてのタグをコロンで区切られた文字列に連結し、:Green:
ANDで一致するすべての製品を削除しています:Motorcycle:
。何かご意見は?
SELECT p.productid,
Concat(':', Group_concat(alltags.tag SEPARATOR ':'), ':') AS taglist
FROM products p
JOIN producttags tag1 USING (productid)
JOIN producttags alltags USING (productid)
WHERE p.active = 1
AND tag1.tag IN ( 'Ford', 'Black', 'Skateboard' )
GROUP BY tag1.productid
HAVING ( taglist NOT LIKE '%:Motorcycle:%'
AND taglist NOT LIKE '%:Green:%' );