下面是我正在运行的大型查询的片段,该查询对充满产品的表执行搜索。此代码段会排除某些产品出现在结果中,除非它被覆盖(指定了标签 ID,例如制定了搜索条件)。
这里有几个标签 ID 及其名称:
标签 ID 576 =“圣诞老人”
标签 ID 123 =“圣诞节”
因此,基本上,下面的内容将排除“tags_gifts_occasion_specific”表中的所有产品,除非它们的标签 ID 为 576(“圣诞老人”)。
AND NOT EXISTS (
SELECT *
FROM tags_gifts_occasion_specific
WHERE tags_gifts_occasion_specific.tag_id != '576'
GROUP BY tags_gifts_occasion_specific.gift_id
)
简单正确...
但问题是,如果相同的产品在此表中,但应用了不同的标签 ID...例如,它也存在于标签“圣诞节”中。
当然,只需添加 'AND Tags_gifts_occasion_specific.tag_id != '123' 就很容易,但是查询不知道它不应该查找哪些附加 ID - 只查找已搜索的 ID。
我一直在尝试类似以下的方法,但没有成功。我想我可以计算一下gift_id出现的次数,如果已经找到了,则忽略任何进一步的内容 - 任何新的输入将不胜感激。
AND NOT EXISTS (
SELECT * , COUNT( * ) AS no_gifts
FROM tags_gifts_occasion_specific
WHERE tags_gifts_occasion_specific.tag_id != '576'
HAVING no_gifts < 1
GROUP BY tags_gifts_occasion_specific.gift_id
)
** 有关按错误排序的更多详细信息 **
所以按 bug 的顺序如下。如果有人搜索“婚礼”和“伴娘”礼物,则应返回婚礼或伴娘礼物,并首先显示两者的匹配项,然后根据受欢迎程度显示其余内容。这适用于“tags_gifts_occasion_specific”表中没有礼物的所有搜索。
SELECT gifts.affiliate_id, gifts.gift_id, gifts.gift_title, gifts.gift_price, gifts.gift_image, gifts.gift_slug
FROM gifts
LEFT JOIN tags_gifts_occasion_specific AS os ON gifts.gift_id = os.gift_id
LEFT JOIN tags_gifts ON tags_gifts.gift_id = gifts.gift_id
LEFT JOIN tags ON tags.id = tags_gifts.tag_id
LEFT JOIN popularity ON popularity.gift_id = gifts.gift_id AND popularity.tag_id = tags.id
WHERE published = '1' AND in_seekgifts = '1'
AND ( (tags_gifts.tag_id = '576' OR tags_gifts.tag_id = '340') )
AND NOT EXISTS (
SELECT * FROM tags_gifts_occasion_specific x WHERE x.gift_id = gifts.gift_id
AND NOT EXISTS(
SELECT * FROM tags_gifts_occasion_specific x1 WHERE x.gift_id = x1.gift_id AND ( tag_id IN (576) OR tag_id in (340) ) )
)
GROUP BY gifts.gift_id
ORDER BY COUNT(*) DESC , popularity.popularity DESC, gifts.gift_popularity DESC, gifts.gift_id DESC
结果的实时示例: http://www.seekgifts.co.uk/wedding_bridesmaid/
我认为正在发生的事情是,它可以看到顶部的产品位于 tags_gifts_occasion_specific 表中的多个标签中,因此按照在此表中找到的次数进行排序。不知道如何解决这个问题?
最佳答案
据我了解,有一个包含产品的表格,还有一个包含每个产品标签的表格。
并且查询预计会跳过具有某些标签的产品,并包含没有这些标签的产品。
例如:
产品
| PRODUCT_ID | PRODUCT_NAME |
|------------|--------------|
| 1 | Product 1 |
| 2 | Product 2 |
| 3 | Product 3 |
| 4 | Product 4 |
| 5 | Product 5 |
标签
| PRODUCT_ID | TAG |
|------------|--------------|
| 1 | Santa |
| 1 | Christmas |
| 2 | Christmas |
| 3 | Santa |
| 4 | Christmas |
| 4 | Exclude |
| 4 | Dont exclude |
| 5 | Christmas |
| 5 | Dont exclude |
我们想要跳过带有标签 Santa
和 Exclude
的产品。
在上面的示例中,我们要跳过产品 1、3 和 4,并包含产品 2、5。
我们可以使用以下相关子查询来做到这一点
SELECT * from products p
WHERE
NOT EXISTS(
SELECT 1 FROM tags t
WHERE t.product_id = p.product_id
AND t.tag IN ( 'Santa', 'Exclude' )
)
;
| PRODUCT_ID | PRODUCT_NAME |
|------------|--------------|
| 2 | Product 2 |
| 5 | Product 5 |
这里是一个工作演示的链接:http://sqlfiddle.com/#!2/d880d/4
<小时/>编辑
<小时/>架构示例
礼物
select * from `gifts`;
| GIFT_ID | GIFT_TITLE |
|---------|------------------------|
| 1 | Red Christmas stocking |
| 2 | Santa Clause Socks |
| 3 | 40th Birthday Mug |
| 4 | Red Bowl |
tags_gifts_occasion_specific
select * from `tags_gifts_occasion_specific`
order by gift_id, tag_id;
| TAG_ID | GIFT_ID |
|--------|---------|
| 3 | 2 |
| 4 | 2 |
| 4 | 3 |
| 3 | 4 |
<小时/>
此查询获取来自 tags_gifts_occasion_specific
的所有条目,但存在 tag_id = 3 的条目除外
select * from `tags_gifts_occasion_specific` x
where not exists(
select 1 from `tags_gifts_occasion_specific` x1
where x.gift_id = x1.gift_id
and tag_id in ( 3 )
);
| TAG_ID | GIFT_ID |
|--------|---------|
| 4 | 3 |
<小时/>
现在我们使用上面的查询从 gifts
表中排除一些记录:
select * from `gifts` g
where not exists(
select 1 from `tags_gifts_occasion_specific` x
where g.gift_id = x.gift_id
and not exists(
select 1 from `tags_gifts_occasion_specific` x1
where x.gift_id = x1.gift_id
and tag_id in ( 3 )
)
);
| GIFT_ID | GIFT_TITLE |
|---------|------------------------|
| 1 | Red Christmas stocking |
| 2 | Santa Clause Socks |
| 4 | Red Bowl |
| 5 | Red 40th Birthday Vase |
<小时/>
关于php - 复杂的 NOT EXISTS MySQL 查询 - 忽略多个匹配项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23313133/