使用HAVING子句时求和为0的行消失,如何解决?
问题与解决方案
问题背景
现有两张数据表:
series表(剧集章节表)
create table series( serie varchar(10), season varchar(10), chapter varchar(10), primary key ( serie, season, chapter) ); insert into series values ('serie_1', 'season_1', 'Chap_1'), ('serie_1', 'season_1', 'Chap_2'), ('serie_1', 'season_2', 'Chap_1'), ('serie_2', 'season_1', 'Chap_1'), ('serie_2', 'season_2', 'Chap_1'), ('serie_2', 'season_2', 'Chap_2'), ('serie_3', 'season_1', 'Chap_1'), ('serie_3', 'season_2', 'Chap_1');
actua表(演员参演薪资表)
create table actua( idActor varchar(10), serie varchar(10), season varchar(10), chapter varchar(10), salary numeric(6), foreign key ( serie, season, chapter) references series, primary key ( idActor, serie, season, chapter) ); insert into actua values ('A1', 'serie_1', 'season_1', 'Chap_1', 1000), ('A1', 'serie_1', 'season_1', 'Chap_2', 1000), ('A1', 'serie_1', 'season_2', 'Chap_1', 1000), ('A2', 'serie_1', 'season_2', 'Chap_1', 1000), ('A3', 'serie_1', 'season_2', 'Chap_1', 1000), ('A1', 'serie_2', 'season_1', 'Chap_1', 1000), ('A2', 'serie_2', 'season_1', 'Chap_1', 2000), ('A2', 'serie_2', 'season_2', 'Chap_1', 2000), ('A2', 'serie_3', 'season_1', 'Chap_1', 3000), ('A4', 'serie_3', 'season_1', 'Chap_1', 500);
需求是:获取薪资总和小于4000的剧集(serie)和季(season),无关联演员的季薪资总和按0计算(比如serie_3的season_2),预期结果如下:
|serie_1|season_1|2000| |serie_1|season_2|3000| |serie_2|season_1|3000| |serie_2|season_2|2000| |serie_3|season_1|3500| |serie_3|season_2| 0|
最初使用以下查询可以得到包含0值的所有季薪资总和:
select serie, season, coalesce(sum(salary), 0) from series natural left join actua group by serie, season order by serie, season
但添加HAVING sum(salary) < 4000后,原本被转为0的行(如serie_3的season_2)消失了,需要解决如何保留该行的问题。
解决方案
原因分析
当某季无关联演员时,sum(salary)的结果是NULL,而在SQL中NULL与任何值进行比较都会返回UNKNOWN,这类行会被HAVING子句过滤掉,所以原本应该显示为0的行消失了。
正确写法
需要在HAVING子句中处理NULL的情况,有两种可行方式:
方式1:在HAVING中使用COALESCE转换NULL为0
select serie, season, coalesce(sum(salary), 0) as total_salary from series natural left join actua group by serie, season having coalesce(sum(salary), 0) < 4000 order by serie, season
方式2:直接判断sum(salary)是否为NULL(因为NULL对应总和0,符合小于4000的条件)
select serie, season, coalesce(sum(salary), 0) as total_salary from series natural left join actua group by serie, season having sum(salary) < 4000 or sum(salary) is null order by serie, season
两种写法都能保留薪资总和为0的行,同时筛选出所有总和小于4000的剧集季数据,得到预期结果。
内容的提问来源于stack exchange,提问作者cnd
相关产品推荐
相关产品推荐

