如何查询MySQL中与指定结果集相反(NOT IN)的数据?
解决MySQL反向查询:获取未关联'red'的礼品卡ID列表
我明白你的需求了——原查询是找出只关联了'red'关键词的礼品卡ID,现在你需要的是它的反向结果:所有未关联'red'关键词的礼品卡ID(包括那些完全没有关联任何关键词的礼品卡)。你用NOT IN遇到问题,大概率是因为NOT IN对NULL值的处理特性,或者子查询的逻辑没匹配需求。下面给你几种可靠的解决方案:
方案1:使用NOT EXISTS(推荐,性能最优)
NOT EXISTS是处理这类反向匹配的首选,它不会受到NULL值的影响,而且MySQL优化器对它的支持很好,查询效率高:
SELECT dgc.id, dgc.name, dgc.has_special FROM d_gift_card dgc WHERE NOT EXISTS ( -- 检查当前礼品卡是否关联了'red'关键词 SELECT 1 FROM keyword k WHERE k.gc_id = dgc.id AND k.keyword = 'red' );
这个查询的逻辑很直接:遍历每一张礼品卡,只要找不到关联的'red'关键词,就将其纳入结果,包括那些没有任何关键词关联的礼品卡。
方案2:LEFT JOIN + IS NULL
这是另一种直观的写法,通过左连接筛选未匹配的记录:
SELECT dgc.id, dgc.name, dgc.has_special FROM d_gift_card dgc -- 左连接关联了'red'的关键词记录 LEFT JOIN keyword k ON dgc.id = k.gc_id AND k.keyword = 'red' -- 筛选出没有匹配到'red'关键词的礼品卡 WHERE k.gc_id IS NULL;
这里的左连接会保留所有礼品卡记录,然后只留下那些没有匹配到'red'关键词的(也就是k.gc_id为NULL的行)。
方案3:修复NOT IN的用法(不推荐,但如果一定要用)
如果你坚持想用NOT IN,需要注意两个关键点:
- 子查询必须返回无
NULL值的ID列表(因为NOT IN遇到NULL会直接返回空结果) - 子查询应该是所有关联了'red'的礼品卡ID,而不是原查询里的“只关联'red'的ID”
调整后的查询如下:
SELECT dgc.id, dgc.name, dgc.has_special FROM d_gift_card dgc WHERE dgc.id NOT IN ( -- 取出所有关联过'red'的礼品卡ID,排除NULL SELECT DISTINCT k.gc_id FROM keyword k WHERE k.keyword = 'red' AND k.gc_id IS NOT NULL );
额外需求:只保留有其他关键词关联的礼品卡
如果你想要的是**确实关联了关键词,但完全没有'red'**的礼品卡(排除无任何关键词的),可以用下面的写法:
用NOT EXISTS + JOIN
SELECT dgc.id, dgc.name, dgc.has_special FROM d_gift_card dgc JOIN keyword k ON dgc.id = k.gc_id WHERE NOT EXISTS ( SELECT 1 FROM keyword k2 WHERE k2.gc_id = dgc.id AND k2.keyword = 'red' ) GROUP BY dgc.id, dgc.name, dgc.has_special;
用GROUP BY + HAVING
SELECT dgc.id, dgc.name, dgc.has_special FROM d_gift_card dgc JOIN keyword k ON dgc.id = k.gc_id GROUP BY dgc.id, dgc.name, dgc.has_special -- 统计'red'关键词的数量,等于0就是未关联 HAVING SUM(CASE WHEN k.keyword = 'red' THEN 1 ELSE 0 END) = 0;
内容的提问来源于stack exchange,提问作者Ethan Allen
相关产品推荐
相关产品推荐

