如何选择一组结果的相反部分(或不在其中的部分)?

v1l68za4  于 2021-06-25  发布在  Mysql
关注(0)|答案(3)|浏览(306)

我有以下mysql查询:

SELECT dgc.name, dgc.id, dgc.has_special 
FROM keyword k 
JOIN d_gift_card dgc ON k.gc_id = dgc.id 
WHERE keyword IN ('red') 
GROUP BY k.gc_id 
HAVING COUNT(DISTINCT k.keyword) = 1

它返回给我一个独特的 id 是那些有 keyword “红色”的。
我想做的是得到一个独特的 id 不具备 keyword “红色”的。基本上与查询所做的相反。
我用not in尝试过这个查询,但是它会返回所有结果,包括那些与它们相关联的“red”结果。正确的方法是什么?

SELECT dgc.name, dgc.id, dgc.has_special 
FROM keyword k 
JOIN d_gift_card dgc ON k.gc_id = dgc.id 
WHERE keyword NOT IN ('red') 
GROUP BY k.gc_id
lo8azlld

lo8azlld1#

我只需将条件移到 having 条款:

SELECT dgc.name, dgc.id, dgc.has_special 
FROM keyword k JOIN
     d_gift_card dgc
     ON k.gc_id = dgc.id 
GROUP BY dgc.name, dgc.id, dgc.has_special  
HAVING SUM( keyword IN ('red') ) = 0;

请注意 GROUP BY 子句匹配未聚合的 SELECT 柱。这是一种最佳实践,而且在大多数情况下是sql标准所要求的。
中的表达式 HAVING 子句统计要删除的行数 'red' . 这个 = 0 说没有。
编写查询最有效的方法可能是:

SELECT dgc.name, dgc.id, dgc.has_special 
FROM d_gift_card dgc
WHERE NOT EXISTS (SELECT 1
                  FROM keyword k         
                  WHERE k.gc_id = dgc.id AND k.keyword IN ('red')
                 );

这可以利用上的索引 keyword(gc_id, keyword) ,完全不需要任何聚合。

falq053o

falq053o2#

一种选择是使用条件聚合并Assert red 从不发生:

SELECT dgc.name, dgc.id, dgc.has_special 
FROM d_gift_card dgc
INNER JOIN
(
    SELECT gc_id
    FROM keyword
    GROUP BY gc_id
    HAVING SUM(CASE WHEN keyword = 'red' THEN 1 ELSE 0 END) = 0
) k
    ON k.gc_id = dgc.id;

对关键字进行检查的逻辑问题 WHERE 子句适用于单个记录,而不是整个id组。因此,即使一个整体组也有阳性匹配,也会留下不匹配的记录。

yb3bgrhw

yb3bgrhw3#

你可以用 MINUS . 像这样:

SELECT dgc.name, dgc.id, dgc.has_special 
FROM keyword k 
JOIN d_gift_card dgc ON k.gc_id = dgc.id 

MINUS

SELECT dgc.name, dgc.id, dgc.has_special 
FROM keyword k 
JOIN d_gift_card dgc ON k.gc_id = dgc.id 
WHERE keyword NOT IN ('red') 
GROUP BY k.gc_id

相关问题