137

I need to sort a PostgreSQL table ascending by a date/time field, e.g. last_updated.

But that field is allowed to be empty or null and I want records with null in last_updated come before non-null last_updated.
Is this possible?

order by last_updated asc -- and null last_updated records first ??
Erwin Brandstetter
667k159 gold badges1.2k silver badges1.3k bronze badges
asked Mar 1, 2012 at 4:11
0

2 Answers 2

260

Postgres has the NULLS FIRST | LAST modifiers for ORDER BY expression:

... ORDER BY last_updated NULLS FIRST

The typical use case is with descending sort order (DESC), which produces the complete inversion of the default ascending order (ASC) with null values first - which is often not desirable. To sort NULL values last:

... ORDER BY last_updated DESC NULLS LAST

To support the query with an index, make it match:

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

Postgres can read btree indexes backwards, so that's effectively almost the same as just:

CREATE INDEX foo_idx ON tbl (last_updated);

For some query plans it matters where NULL values are appended. See:

answered Mar 1, 2012 at 6:14
Sign up to request clarification or add additional context in comments.

1 Comment

Worth noting: NULLS FIRST is default for DESC, NULLS LAST is default for ASC.
25

You can create a custom ORDER BY using a CASE statement.
The CASE statement checks for your condition and assigns to rows which meet that condition a lower value than that which is assigned to rows which do not meet the condition.
It's probably easiest to understand given an example:

 SELECT last_updated 
 FROM your_table 
ORDER BY CASE WHEN last_updated IS NULL THEN 0 ELSE 1 END, 
 last_updated ASC;
answered Mar 1, 2012 at 4:19

5 Comments

Also, but you probably know this, ASC is the default sorting order so you do not necessarily need to type it.
NULLS FIRST is also the ANSI compliant way to write nulls first.
@a_horse_with_no_name It's useful in my case because I want to ignore the value if it's not null, and then sort by another column instead. (Im sorting notifications — unseen first (then seenAt is null), but if seen, then I sort by createdAt instaed)
Agreed; I found this useful when just wanting to sort by whether or not a value was present (in this case, a date) — and then sorting by another value secondarily. NULLS FIRST still sorted by the actual value if the value was non-null. This did the trick for me. Thanks!
This is the best solution. Can be used with anything else like for eg deleted_at >= xyz time then 0 else 1 ...

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.