我有一个表product
,其中包含title
(varchar)或availability
(bool)等字段。
用户可以按名称(product.title
)搜索产品,但也可以应用某些过滤器(例如类型,生产者等)。
我使用SELECT
和INNER 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。
对此事的任何支持都会有所帮助。谢谢!
答案 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列以获得未击中任何过敏原的产品。