首先让我描述一些背景。我们有一个包含所有产品的表格,以及一个包含“产品标签”列表(材料/尺寸/类型)的表格,以及一个包含分配给产品的标签列表的表格('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
答案 0 :(得分:1)
您的查询存在一些问题。
首先,您有一个CROSS JOIN,它将生成一个笛卡尔积,从products
返回的每一行都将与product_assigned_tags
中的每一行匹配。
此外,由于WHERE子句中的谓词,您的下两个连接实际上根本不是LEFT连接(它们不是外连接)。检查value = 'foo'
实际上是否定了外连接。
另外,你的一些谓词是多余的。
如果value = 'silver'
的计算结果为true,那么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'案例?例如:客户选择查看材料为“gold”或“silver”的所有产品?
A:表达联接谓词中的OR
条件,例如
AND tags_0.`value` IN ('silver','gold')
相当于:
AND ( tags_0.`value` = 'silver' OR tags_0.`value` = 'gold')