我有以下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
答案 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