添加cities列后SQL查询返回空结果,求HAVING子句修正方案
问题分析与解决
首先看你提供的查询语句,存在两个核心问题导致修改后返回空结果:
1. 表别名错误
不管是原始查询还是修改后的查询,select子句里用了d.continent、d.country_name、di.is_preferred,但from子句里只定义了continent c和countries ct这两个别名,根本没有d和di——这属于笔误,会直接导致查询报错(你说原始查询能运行,可能是实际写的时候别名是对的,这里输入时写错了)。
2. GROUP BY粒度错误导致HAVING条件不满足
你原本的逻辑是按大陆、国家、首选标记分组,筛选出分组后数量大于1的记录。但修改后把c.cities加入了GROUP BY,这会让分组粒度变细到「大陆-国家-首选标记-单个城市」。如果每个城市对应的关联数据只有1条,那么每个分组的count(1)就会变成1,自然满足不了having count(1) >1的条件,所以返回空结果。
修正方案
如果你想保留原有筛选逻辑,同时展示符合条件国家的所有城市列表,有两种常用方法:
方法1:先筛选符合条件的国家,再关联获取城市
先通过子查询找出拥有超过1个首选目的地的大陆对应的国家,再关联continent表获取城市:
-- 子查询先筛选符合条件的国家 SELECT c.continent, ct.country_name, ct.is_preferred, c.cities FROM continent c JOIN countries ct ON c.cid = ct.id WHERE ct.preferred = 'Y' -- 注意:Y要加单引号,否则会被识别为字段名 AND ct.country_name IN ( SELECT ct_inner.country_name FROM continent c_inner JOIN countries ct_inner ON c_inner.cid = ct_inner.id WHERE ct_inner.preferred = 'Y' GROUP BY c_inner.continent, ct_inner.country_name, ct_inner.is_preferred HAVING COUNT(1) > 1 ) ORDER BY ct.country_name ASC;
方法2:用聚合函数合并城市列表(适合一行展示一个国家的所有城市)
如果想把同一个国家的城市合并成一个字符串展示,不用拆分多行,可以用字符串聚合函数(不同数据库函数名不同,比如MySQL用GROUP_CONCAT,PostgreSQL用STRING_AGG,SQL Server用STRING_AGG):
-- MySQL版本 SELECT c.continent, ct.country_name, ct.is_preferred, GROUP_CONCAT(c.cities SEPARATOR ', ') AS cities_list, COUNT(1) FROM continent c JOIN countries ct ON c.cid = ct.id WHERE ct.preferred = 'Y' GROUP BY c.continent, ct.country_name, ct.is_preferred HAVING COUNT(1) > 1 ORDER BY ct.country_name ASC; -- PostgreSQL版本 SELECT c.continent, ct.country_name, ct.is_preferred, STRING_AGG(c.cities, ', ') AS cities_list, COUNT(1) FROM continent c JOIN countries ct ON c.cid = ct.id WHERE ct.preferred = 'Y' GROUP BY c.continent, ct.country_name, ct.is_preferred HAVING COUNT(1) > 1 ORDER BY ct.country_name ASC;
另外注意:ct.preferred = Y这里的Y必须加单引号'Y',否则数据库会把Y当成字段名,导致找不到字段报错。
内容的提问来源于stack exchange,提问作者Yuan
相关产品推荐
相关产品推荐

