考虑以下模式:
create table cities (
id serial primary key,
name text not null
);
insert into cities
(name)
values
('NY'),
('SF'),
('LA');
create table users (
id serial primary key,
name text not null,
city_id int not null references cities (id)
);
insert into users
(name, city_id)
values
('Tom', 1),
('Anna', 1),
('Frank', 2);
还有这些疑问:
--- A ---
with foo as (
select c.name, count(u.id) as count from cities c
left join users u on u.city_id=c.id
group by c.name
)
select name, case when count > 0 then count else null end from foo
order by count;
--- B ---
with foo as (
select c.name, count(u.id) as count from cities c
left join users u on u.city_id=c.id
group by c.name
)
select name, case count > 0 when true then count else null end from foo
order by count;
--- C ---
with foo as (
select c.name, count(u.id) as count from cities c
left join users u on u.city_id=c.id
group by c.name
)
select name, case count when 0 then null else count end from foo
order by count;
查询 A 和 B(一般和简单情况形式)返回
null
作为第一个元素,而查询 C 返回 null
最后一个。
NULLS LAST
也不适用于 A 和 B,而 NULLS FIRST
则适用于 C。
为什么?
这与
NULLS FIRST/LAST
无关。 NULLS FIRST
是默认值,您尚未指定。
您的
case
列均未命名。 文档说:
如果未使用
指定输出列名称,系统将分配默认列名称。对于简单的列引用,这是引用列的名称。对于函数调用,这是函数的名称。对于复杂的表达式,系统会生成一个通用名称。AS
因此,在前两个中,该列称为
case
,而在后者中,该列称为 count
。确切的原因尚不清楚,因为它们都是表达式,但名称是特定于实现的,你不应该依赖它。
由于前两个查询有一个
case
列,因此它是按基本 count
列排序。而在第三个查询中,它按实际计算的 case
表达式进行排序。
您可以在这个fiddle中看到它的实际效果。
请注意,由于
COUNT()
返回的值永远不会小于 0
,因此您可以简化为 nullif(count(u.id), 0)
并且只有一个级别而不是 CTE。