我有3个表:Products,Tags和products_tags(产品和标签之间的多对多)。 在我的架构中,产品可以包含零到多个标签,标签可以包含零到多个产品。 现在我想选择具有特定标签且没有特定标签的产品。
产品表:
idproducts / name
1 / samsung galaxy
2 / samsung note1
3 / samsung note2
4 / iphone 4gs
标签表:
idtags / word
1 / samsung
2 / galaxy
3 / note1
4 / note2
5 / iphone
6 / 4gs
7 / apple
Products_Tags表:
产品/标签
1/1
1/2
2/1
2/3
3/1
3/4
4/5
4/6
我有下面的查询,但是它给了我带有标签的产品i 没有想要因为他们有其他标签而且由于加入它们会出现在结果集中。
SELECT * FR0M产品AS p
JOIN products_tags AS pt ON pt.product = p.idproducts JOIN tags AS t ON t.idtags = pt.tag WHERE t.word IN ('samsung', 'mobile') AND t.word NOT IN ('note1', 'note2')
如果我想要三星Galaxy并且我定义了像'samsung'这样的标签而没有'note1'和'note2'。对此有什么疑问?
P.S。我想也许应该使用EXISTS或NOT EXISTS,但我只是无法弄清楚我应该如何使用它们。
先谢谢
答案 0 :(得分:1)
您的查询无效,因为联接会选择包含标记三星的所有元素,包括samsung note 1
和samsung note 2
。您可以使用group_concat
对所有代码名称进行分组,然后使用like
或Regexp
对其进行过滤,如下所示:
select *, GROUP_CONCAT(t.word) tagname from products as p
inner JOIN products_tags AS pt ON pt.products = p.productid
inner Join tags t on t.idtags = pt.tags
group by p.productid
having tagname not REGEXP 'note1|note2'
and tagname REGEXP 'samsung|mobile'
一些重要资源:
答案 1 :(得分:0)
您希望所有产品都带有三星或手机标签,但没有备注1或note2标签?
SELECT * FR0M products AS p
JOIN products_tags AS pt ON pt.product = p.idproducts
JOIN tags AS tp ON tp.idtags = pt.tag and (tp.word = 'samsung' or tp.word = 'mobile')
JOIN tags AS tn ON tn.idtags = pt.tag and tn.word <> 'note1' and tn.word <> 'note2'
将是一种方式。
你的尝试不起作用,因为任何满足in子句的行都不可能满足于一个。三星和手机都不是note1或note2
上面有一个连接来获取三星或移动设备,然后再次加入标签表(使用不同的别名)来获取没有note1或note2标签的所有那些。