MySQL选择连接多对多表加上IN和NOT IN

Posted

技术标签:

【中文标题】MySQL选择连接多对多表加上IN和NOT IN【英文标题】:MySQL select join many to many tables plus IN and NOT IN 【发布时间】:2012-09-27 21:45:54 【问题描述】:

我有 3 个表:产品、标签和 products_tags(产品和标签之间的多对多)。 在我的架构中,一个产品可以有零到多个标签,一个标签可以有零到多个产品。 现在我想选择有特定标签而没有特定标签的产品。

产品表:

idproducts / 名称

1 / 三星银河

2/三星note1

3/三星note2

4 / iphone 4gs

标签表:

idtags / 单词

1 / 三星

2 / 星系

3 / 注释1

4 / note2

5 / iphone

6 / 4gs

7 / 苹果

Products_Tags 表:

产品/标签

1 / 1

1 / 2

2 / 1

2 / 3

3 / 1

3 / 4

4 / 5

4 / 6

我有下面的查询,但它给了我带有标签的产品,我不想要因为它们有一些其他标签,并且作为连接的结果,它们出现在结果集中。

选择 * FR0M 产品作为 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,并且我定义了像“三星”这样的标签,而没有“note1”和“note2”。对此的查询是什么?

附:我想也许应该使用 EXISTS 或 NOT EXISTS,但我只是不知道应该如何使用它们。

提前致谢

【问题讨论】:

【参考方案1】:

您的查询不起作用,因为连接选择了所有带有 samsung 标签的元素,包括 samsung note 1samsung note 2。您可以使用group_concat 对所有标签名称进行分组,然后使用likeRegexp 对其进行过滤,如下所示:

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'

一些重要资源:

Group_Concat Regexp

【讨论】:

tnx Kasi,它现在可以工作了,但是除了正则表达式,我还有其他选择吗?我不熟悉它,如果可以的话,我更喜欢使用其他选项 Regexp 将允许您将多个表达式组合在一起,但您也可以为此使用Like,例如tagname not like '%note1%' and tagname not like '%note2%'【参考方案2】:

您想要所有带有 samsung 或 mobile 标签但没有 note 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 子句的任何行都不可能满足 not in one。三星和手机都不是note1或note2

上面进行了一次连接以获取三星或移动设备,然后再次连接到标签表(使用不同的别名)以获取所有没有note1或note2标签的人。

【讨论】:

tnx Tony,但它仍然给了我我不想要的产品 'samsung note1' 和 'samsung note2' 使用您的查询,我得到了带有“三星”标签的全部 3 种产品。我需要排除带有我不想要的标签的产品,即使同一产品有一些我想要的标签。例如,即使产品“samsung note1”和“samsung note2”有标签“samsung”,但它们有标签“note1”和“note2”,我希望它们不在结果集中。我只想要有标签'samsung'但没有标签'note1'和'note2'的产品'samsung galaxy' Ahhhhhhhh,嗯,我得考虑一下这个

以上是关于MySQL选择连接多对多表加上IN和NOT IN的主要内容,如果未能解决你的问题,请参考以下文章

如何从多对多表中选择一对一关系

在 Django 中加入多对多表

跨多对多表的关系

插入一张多对多表并加入表休眠

如何在多对多表上级联删除

Spring Data JPA 多对多表查询