SELECT 中的 CASE 如何影响 ORDER BY 结果

问题描述 投票:0回答:1

考虑以下模式:

    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。

为什么?

sql postgresql case sql-order-by
1个回答
2
投票

这与

NULLS FIRST/LAST
无关。
NULLS FIRST
是默认值,您尚未指定。

您的

case
列均未命名。 文档说:

如果未使用

AS
指定输出列名称,系统将分配默认列名称。对于简单的列引用,这是引用列的名称。对于函数调用,这是函数的名称。对于复杂的表达式,系统会生成一个通用名称。

因此,在前两个中,该列称为

case
,而在后者中,该列称为
count
。确切的原因尚不清楚,因为它们都是表达式,但名称是特定于实现的,你不应该依赖它

由于前两个查询有一个

case
列,因此它是按基本
count
列排序。而在第三个查询中,它按实际计算的
case
表达式进行排序。

您可以在这个fiddle中看到它的实际效果。

请注意,由于

COUNT()
返回的值永远不会小于
0
,因此您可以简化为
nullif(count(u.id), 0)
并且只有一个级别而不是 CTE。

© www.soinside.com 2019 - 2024. All rights reserved.