为什么当我使用having时,带有0的行会消失?

cnd*_*cnd 3 sql postgresql null coalesce having

我有这个表:

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');

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)
               ;

Run Code Online (Sandbox Code Playgroud)

我正在尝试获取工资总和小于 4000 的系列和季节,并且如果系列的任何季节没有关联的演员,则它们的总和将计为零(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|
Run Code Online (Sandbox Code Playgroud)

首先,我尝试进行查询以获取该系列,其中包含不同季节以及每个季节的工资总和,此外在空行中替换 0:

select serie, season, coalesce(sum(salary), 0) 
from series natural left join actua group by serie, season order by serie, season
Run Code Online (Sandbox Code Playgroud)

我得到了我预期的解决方案(因为所有工资的总和都小于4000)然后我尝试显示工资小于4000的行,这实际上是所有行;使用having子句:

select serie, season, coalesce(sum(salary), 0) 
from series natural left join actua group by serie, season having sum(salary) < 4000 order by serie, season
Run Code Online (Sandbox Code Playgroud)

我使用合并的行消失了,使用having时如何显示它?

Lau*_*lbe 5

这是因为从外连接得到的 NULL 值之和为 NULL,并且 NULL 不小于 4000:

\n
SELECT CASE WHEN NULL < 4000\n            THEN 'NULL is less than 4000'\n            ELSE 'it is not true that NULL is less than 4000'\n       END;\n                    case                    \n\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\n it is not true that NULL is less than 4000\n
Run Code Online (Sandbox Code Playgroud)\n

实际上,如果将 NULL 与任何内容进行比较,结果始终是 NULL(“未知”),这是不正确的。

\n

所以你也必须coalesce()在子句中使用:HAVING

\n
... HAVING coalesce(sum(salary), 0) < 4000\n
Run Code Online (Sandbox Code Playgroud)\n