按列升序排序,但将NULL值放在前面?

125

我需要按照一个日期/时间字段(例如last_updated)升序排序PostgreSQL表格。

但是该字段允许为空或为null,而我希望在last_updated为null的记录排在非空last_updated记录之前。
这个是否可能实现?

order by last_updated asc  -- and null last_updated records first ??
2个回答

238

Postgres在ORDER BY表达式中有NULLS FIRST | LAST修饰符:

... ORDER BY last_updated NULLS FIRST

典型的使用情况是降序排序(DESC),这会完全颠倒默认的升序排序(ASC),并将空值放在最前面 - 这通常是不可取的。要将NULL值排在最后:

... ORDER BY last_updated DESC NULLS LAST

为了支持带有索引的查询,请让它匹配:

CREATE INDEX foo_idx ON tbl (last_updated DESC NULLS LAST);

Postgres可以反向读取B树索引,因此实际上几乎与以下操作相同:

CREATE INDEX foo_idx ON tbl (last_updated);

对于某些查询计划,NULL值的附加位置很重要。请参见:


32
我做了,这就是我得到这个页面的方式 :) - ibrewster
2
感谢您的回答。SQLite3添加了这个功能,在使用之前,我想确保它与PostgreSQL兼容。结果发现这是现在的标准事情! - Brad
3
值得注意的是:NULLS FIRSTDESC 的默认值,NULLS LASTASC 的默认值。 - Ivan Rubinson

21

您可以使用CASE语句创建自定义ORDER BY。
CASE语句检查您的条件,并为满足该条件的行分配比未满足条件的行更低的值。
最好通过示例来理解:

  SELECT last_updated 
    FROM your_table 
ORDER BY CASE WHEN last_updated IS NULL THEN 0 ELSE 1 END, 
         last_updated ASC;

1
此外,但你可能已经知道,ASC 是默认的排序顺序,所以你不一定需要输入它。 - mechanical_meat
4
"NULLS FIRST" 是按照 ANSI 标准书写空值(null)在前的方式。 - user330315
3
@a_horse_with_no_name 在我的情况下很有用,因为我想忽略值如果它不是空的,然后按另一列排序。 (我正在对通知进行排序:未看到的通知排在前面(然后 seenAt 为 null),但如果已看到,则按 createdAt 排序) - KajMagnus
3
同意;当我只想按值(在这种情况下是日期)是否存在进行排序,然后再进行次要排序时,我发现这很有用。NULLS FIRST仍然按实际值对非空值进行排序。这对我起到了作用。谢谢! - Ben Kreeger
1
这是最佳解决方案。可以与其他任何东西一起使用,例如 deleted_at >= xyz time,则为0,否则为1... - Koushik Das

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接