0

最初にいくつかの背景を説明しましょう。すべての製品を含むテーブル、「製品タグ」(材料/サイズ/タイプ)のリストを含むテーブル、および製品に割り当てられたタグのリストを含むテーブル(「tag_id」= > 1(材料)、'値'=>'ゴールド'、'製品'=> 123)

これに似たクエリを使用して特定の製品を除外しようとしていますが、機能しないようです。誰かが正しい方向にいくつかのポインタを提供できますか?

SELECT DISTINCT `products`.* FROM `products`,`product_assigned_tags`
LEFT JOIN `product_assigned_tags`   AS tags_0 ON tags_0.`tag_id` = 1
LEFT JOIN `product_assigned_tags`   AS tags_1 ON tags_1.`tag_id` = 2
WHERE (
    ((tags_0.`value` = 'silver' ) AND (tags_0.`value` != 'gold' ) ) AND
    ((tags_1.`value` = 'small' ) AND (tags_1.`value` != 'large' ) )
) AND (`products`.`type` = '2' OR `products`.`type` = '1' ) LIMIT 0, 30
4

1 に答える 1

1

クエリに問題があります。

まず、デカルト積を生成する CROSS JOIN があります。 から返されるすべての行は、 のすべての行productsと一致しproduct_assigned_tagsます。

また、次の 2 つの結合は、WHERE 句の述語のため、実際には LEFT 結合ではありません (外部結合ではありません)。のチェックはvalue = 'foo'、外部結合を事実上否定しています。

また、述語の一部は冗長です。

value = 'silver'が true と評価された場合は、 value != 'gold'true であることが保証されます。その不等式の述語を含める必要はありません。


product_assigned_tags表は製品に関連しているようで、product_id列は への外部キーproducts.idです。(スキーマ定義がないので、私はそれを推測しているだけです。

SELECT DISTINCT p.*
  FROM `products` p
  JOIN `product_assigned_tags` tags_0
    ON tags_0.product_id = p.id
   AND tags_0.`tag_id` = 1
   AND tags_0.`value` = 'silver'
  JOIN `product_assigned_tags` tags_1 
    ON tags_1.product_id = p.id 
   AND tags_1.`tag_id` = 2
   AND tags_1.`value` = 'small'
 WHERE p.`type` IN ('1','2')
 ORDER BY 1
 LIMIT 0,30

Q: JOIN で「OR」ケースを処理するにはどうすればよいですか? 例: クライアントは、素材が「金」または「銀」のすべての製品を表示することを選択しましたか?

A:OR結合述語で条件を 表現します。

   AND tags_0.`value` IN ('silver','gold')

これは次と同等です:

   AND ( tags_0.`value` = 'silver' OR tags_0.`value` = 'gold')
于 2012-12-14T18:56:37.880 に答える