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.

此外,由于 WHERE 子句中的谓词,您接下来的两个联接实际上根本不是 LEFT 联接(它们不是外部联接)。的检查value = 'foo'有效地否定了外部连接。

此外,您的某些谓词是多余的。

如果value = 'silver'计算结果为真,则value != 'gold'保证为真,则无需包含该不等式谓词。


看起来该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

问: 我将如何处理带有 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 回答