如何选择相反的(或者不是什么)一组结果?

时间:2018-05-06 23:38:53

标签: mysql sql select join

我有以下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进行此查询,但它会带回所有结果,包括与其关联的“红色”结果。什么是正确的方法?

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 

3 个答案:

答案 0 :(得分:1)

一种选择是使用条件聚合并断言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组。因此,即使整个群体也有正面匹配,它也会留下不匹配的记录。

答案 1 :(得分:1)

我只需将条件移到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)上的索引,并且根本不需要任何聚合。

答案 2 :(得分:-1)

您可以使用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