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

时间:2014-04-26 15:46:05

标签: php mysql sql phpmyadmin

以下是我正在运行的大型查询的代码段,该代码会对装满产品的表执行搜索。此片段不会将某些产品排除在结果中,除非它被覆盖(标记ID已指定,例如,制定了搜索条件)。

这里有几个标签ID及其名称:

标签ID 576 ='圣诞老人'

标签ID 123 ='圣诞节'

所以基本上下面将排除'tags_gifts_occasion_specific'表中的所有产品,除非它们的标签ID为576('Santa')。

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 ...例如它也在那里用于标记'Christmas'。

当然,添加'AND tags_gifts_occasion_specific.tag_id!='123'会很容易,但是查询不知道它不应该查找哪些附加ID - 只有已经搜索过的ID。 / p>

我一直在玩类似以下的东西,但不成功。我以为我可以计算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命令的进一步细节**

所以bug的顺序如下。如果有人搜索“婚礼”和'bridemaid'礼品,婚礼或新娘礼品应该与首先显示的匹配返回,然后其余的基于受欢迎程度。这适用于'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表中,用于多个标签,因此按照在此表中找到的次数进行排序。不确定如何绕过这个?

1 个答案:

答案 0 :(得分:1)

据我所知,有一个包含产品的表格,每个产品都有一个带标签的表格
该查询有望跳过具有某些标记的产品,并包含不具备这些标记的产品。


例如:

产品

| 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的rpoducts 在上面的示例中,我们要跳过产品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