php - 复杂的 NOT EXISTS MySQL 查询 - 忽略多个匹配项

标签 php mysql sql phpmyadmin

下面是我正在运行的大型查询的片段,该查询对充满产品的表执行搜索。此代码段会排除某些产品出现在结果中,除非它被覆盖(指定了标签 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 |

我们想要跳过带有标签 SantaExclude 的产品。
在上面的示例中,我们要跳过产品 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 |
<小时/>

这里是演示链接:http://sqlfiddle.com/#!2/558422/5

关于php - 复杂的 NOT EXISTS MySQL 查询 - 忽略多个匹配项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23313133/

相关文章:

sql - Oracle中的自增(删除后调整ID顺序)

sql - ActiveRecord 的意外行为包括

javascript - 选择选项值时如何引用页面?

php - 如何打包 PHP 应用程序\脚本?

php - 有什么方法可以将 ROLLUP (mysql) 数字捕获为 php 中的值?

mysql - SQL从同一个表内的子组中多选一行

python - 有没有办法在 python 中将 SQL 表用作类或对象?

PHP:带有 mysqli 的未知 MySQL 服务器主机

php - 在 session 中存储错误消息并显示在另一个页面上

mysql - MySQL 是否支持部分索引?