INNER JOIN with NOT IN返回错误的结果

时间:2016-01-12 02:37:01

标签: mysql

我有一个表product,其中包含title(varchar)或availability(bool)等字段。

用户可以按名称(product.title)搜索产品,但也可以应用某些过滤器(例如类型,生产者等)。 我使用SELECTINNER JOIN一起解决了这个问题。生成的查询的示例如下所示:

SELECT z.* 
FROM product z 
WHERE (z.title LIKE "%bread%") 
AND z.availability = 1 
AND z.category IN (4,5,6);

这非常有效。但是,产品也标有“过敏标签”(例如 gluten )。 不幸的是,产品可以容纳任何数量的“过敏标签”,因此我需要使用交联表(crosslink__productXproduct_allergy_tag):

id int not null primary key auto_increment
productId int
allergyTagID int

标记存储在表product_allergy_tag中,使用id作为主键,标记的标题。 当然,在搜索无麸质的产品时,生成的查询将如下所示:

SELECT z.* 
FROM product z  
INNER JOIN crosslink__productXproduct_allergy_tag a ON z.id = a.productId  
WHERE (z.title LIKE "%bread%")
AND z.availability = 1  
AND a.allergyTagId IN (15)

(15为麸质标签的ID)。

但是,如果我以与上面所示相同的方式运行搜索,那么搜索无谷蛋白产品最终会显示 面筋的产品。< / p>

所以我想:我只需要颠倒逻辑:

而不是:

a.allergyTagId IN (15)

它将是:

a.allergyTagId NOT IN (15)

然而,由于我不明白的原因,查询仍会返回一些带有过敏标签的产品,尽管它不会返回所有产品。

我尝试通过测试各种选项和比较结果来达到核心目标,但无济于事。

谣言有它,我不是SQL wiz。

对此事的任何支持都会有所帮助。谢谢!

2 个答案:

答案 0 :(得分:2)

<MetaData>

编辑:您想要的是产品列表,不包括过敏标签为15的产品列表中的产品。子查询找到过敏标签为15的产品列表,主要查询选择所有不具有'的'那些。

答案 1 :(得分:1)

问题是,联接的工作方式,它会与每场比赛一起加入,所以你得到:

产品A - 过敏原A. 产品A - 过敏原B. 产品B - 过敏原C

您也没有得到任何没有过敏原的产品,因为INNER JOIN需要至少选择一种过敏原。

你想要的是一个JOIN并测试过敏原是否为NULL。类似的东西:

SELECT z.* FROM product z LEFT JOIN crosslink__productXproduct_allergy_tag a
  ON z.id = a.productId AND a.allergyTagId IN (15) WHERE (z.title LIKE 
 "%bread%") AND z.availability = 1 AND a.allergyTagId IS NULL

这是在JOIN时检查过敏原。如果存在匹配项,则每个匹配项将包含一行,并将allergyTagId设置为匹配的ID,如果匹配任何匹配项,则该列中将包含NULL。然后,过滤NULL列以获得未击中任何过敏原的产品。