371

I have a SQL table with a datetime field. The field in question can be null. I have a query and I want the results sorted ascendingly by the datetime field, however I want rows where the datetime field is null at the end of the list, not at the beginning.

Is there a simple way to accomplish that?

Machavity
  • 30,841
  • 27
  • 92
  • 100
David Božjak
  • 16,887
  • 18
  • 67
  • 98
  • 6
    Exact duplicate of http://stackoverflow.com/questions/151195/possible-to-use-sql-to-sort-by-date-but-put-null-dates-at-the-back-of-the-results – Bill Karwin Sep 30 '09 at 15:03
  • See also http://stackoverflow.com/questions/15121093/django-adding-nulls-last-to-query/35494930#35494930 and https://code.djangoproject.com/ticket/13312 – Risadinha Oct 21 '16 at 10:38

14 Answers14

471
select MyDate
from MyTable
order by case when MyDate is null then 1 else 0 end, MyDate
D'Arcy Rittich
  • 167,292
  • 40
  • 290
  • 283
  • 2
    Note however that if you place an index on the sort column to improve performance(*), then this method will somewhat complicate the query plan and lose much of the performance benefit. * - indexes provided the data presorted, hence avoiding a sort per query execution. It's advisable to filter out the NULL records if possible to avoid this issue completely. – redcalx Nov 14 '12 at 15:05
  • 2
    Nice answer also given here with all possible ways with advantage and disadvantages http://nickstips.wordpress.com/2010/09/30/sql-order-by-with-null-values-last/ – sudhansu63 Sep 12 '13 at 07:17
  • 55
    `order by case when MyDate is null then 1 else 0 end` is a really long way of saying `ORDER BY MyDate IS NULL` – Martin Oct 15 '15 at 18:43
  • 10
    @Martin Note this question is not tagged mysql. I provided a generalized solution - there are many different ways of doing the same thing across different dbs. – D'Arcy Rittich Oct 16 '15 at 14:15
  • 1
    If order by 0 throws an error, why does a case expression that returns 0 work? – Kyle Delaney Jul 25 '16 at 22:43
  • 2
    @KyleDelaney Because `order by 0` gets interpreted as a column index, and the column indexes are 1-based. To sort a query by the 3rd column you can say `order by 3` (which is a terrible idea for production queries), but very handy (as is `*`) when experimenting. – D'Arcy Rittich Jul 26 '16 at 15:26
  • From the [SQL Server Docs](https://msdn.microsoft.com/en-us/library/ms188385.aspx?f=255&MSPPError=-2147217396) : _A sort column can be specified as a name or column alias, or a nonnegative integer representing the position of the column in the select list._ – D'Arcy Rittich Jul 26 '16 at 15:29
  • 2
    @KyleDelaney as mentioned before, the 0 in 'order by 0' is taken as a column index whereas the 0 in the case statement is taken to be a value in a 'dummy' column (if that makes sense). You can also try 'order by (select 0)' and that will work as the db engine interprets it as a column value for a dummy column that has been added just for the purposes of sorting the output. – umbersar Jul 23 '20 at 06:21
  • also, why do we map null to 1 ? – MasterJoe Sep 01 '20 at 20:03
  • @MasterJoe see this comment https://stackoverflow.com/questions/1498648/sql-how-to-make-null-values-come-last-when-sorting-ascending/1498667?noredirect=1#comment20167656_12767777 – D'Arcy Rittich Sep 03 '20 at 18:08
  • how about `ORDER BY NVL(MyDate,'01.01.1900')` or `COALESCE()` isntead of oracles `NVL()` – Stefan Höltker Feb 01 '22 at 13:22
209

(A "bit" late, but this hasn't been mentioned at all)

You didn't specify your DBMS.

In standard SQL (and most modern DBMS like Oracle, PostgreSQL, DB2, Firebird, Apache Derby, HSQLDB and H2) you can specify NULLS LAST or NULLS FIRST:

Use NULLS LAST to sort them to the end:

select *
from some_table
order by some_column DESC NULLS LAST
  • 23
    AFAIK `NULLS FIRST` and `NULLS LAST` have been added in SQL:2003 but there is no standard implementation available throughout the different DMBS'. Depending on the database engine, use `ORDER BY expr some_column DESC NULLS LAST` (Oracle) , `ORDER BY ISNULL(some_column, 1), some_column ASC` (MSSQL) or `ORDER BY ISNULL(some_column), some_column ASC` (MySQL wih a different ISNULL() implementation). – SaschaM78 Jan 23 '13 at 09:06
  • 6
    @SaschaM78: the default sorting of NULLs is DBMS dependent. Some sort them at the end, some at the beginning. Some don't bother about `ASC`/`DESC` with nulls some do. So the only way to ensure this, is to use `NULL FIRST/LAST` **if** the DBMS supports it. At it *documents* what you intend. The usage of `isnull()` or other functions is a workaround for the missing support for `NULLS FIRST/LAST` (which is suported by Oracle, PostgreSQL, DB2, Firebird, Apache Derby, HSQLDB and H2) –  Jan 23 '13 at 09:15
  • You are perfectly right, I just wanted to add the fact that there are quite some DBMS around that do not follow the standard (yet) or have their specialities like Oracle requiring the `expr` keyword when using NULLS FIRST/LAST. And thanks about the nulls being shown first/last varying from database type to type, didn't know that! – SaschaM78 Jan 23 '13 at 11:25
  • 3
    This looks promising, but sadly, I tried it and `NULLS LAST` did not work in my MySQL database. – RedDragonWebDesign Oct 20 '17 at 21:50
  • 2
    @AdmiralAdama: you can always upgrade to Postgres –  Oct 20 '17 at 22:27
42

I also just stumbled across this and the following seems to do the trick for me, on MySQL and PostgreSQL:

ORDER BY date IS NULL, date DESC

as found at https://stackoverflow.com/a/7055259/496209

Community
  • 1
  • 1
Luksurious
  • 991
  • 9
  • 15
22

If your engine allows ORDER BY x IS NULL, x or ORDER BY x NULLS LAST use that. But if it doesn't these might help:

If you're sorting by a numeric type you can do this: (Borrowing the schema from another answer.)

SELECT *          
FROM Employees
ORDER BY ISNULL(DepartmentId*0,1), DepartmentId;

result showing sorted by DepartmentId with nulls last

Any non-null number becomes 0, and nulls become 1, which sorts nulls last because 0 < 1.

You can also do this for strings:

SELECT *
FROM Employees
ORDER BY ISNULL(LEFT(LastName,0),'a'), LastName

result showing sorted by LastName with nulls last

Any non-null string becomes '', and nulls become 'a', which sorts nulls last because '' < 'a'.

This even works with dates by coercing to a nullable int and using the method for ints above:

SELECT *
FROM Employees
ORDER BY ISNULL(CONVERT(INT, HireDate)*0, 1), HireDate

(Lets pretend the schema has HireDate.)

These methods avoid the issue of having to come up with or manage a "maximum" value of every type or fix queries if the data type (and the maximum) changes (both issues that other ISNULL solutions suffer). Plus they're much shorter than a CASE.

infogulch
  • 1,182
  • 10
  • 22
16

You can use the built-in function to check for null or not null, as below. I test it and its working fine.

select MyDate from MyTable order by ISNULL(MyDate,1) DESC, MyDate ASC;

devrys
  • 1,571
  • 3
  • 27
  • 43
  • For dates to work with mssql I found useful putting a far in the future date in the ISNULL function i.e. ISNULL(MyDate,'2100-01-01') – Emi-C Jul 18 '17 at 09:12
  • In MySQL, it says I am passing too many parameters. I got this to parse by doing `ISNULL(MyDate) DESC, MyDate ASC`, but it did not sort in the correct order. – RedDragonWebDesign Oct 20 '17 at 21:59
15
order by coalesce(date-time-field,large date in future)
Chris Van Opstal
  • 36,423
  • 9
  • 73
  • 90
Gratzy
  • 9,164
  • 4
  • 30
  • 45
  • 10
    While this will generally work, it should be noted this answer has a few issues: large date in future may collide with or be less than actual data, resulting in an imperfect sort. Also, it is a "magic number" solution that is not self-documenting. – D'Arcy Rittich Sep 30 '09 at 17:48
  • This happens to be a great alternative to the @RedFilter answer when you need to compare the column in question to another date column. I use this for union seniority list. If employee has a Qualified date (which is nullable) , that date bubbles record to the top, otherwise use HireDate. Using ORDER BY ISNULL(QualifiedDate,'1-1-2099') , HireDate ,LastName, etc makes the Qualified date not conflict with HiredDate date and the correct senirity list is produced. – Alan Fisher Oct 06 '15 at 23:49
13

When your order column is numeric (like a rank) you can multiply it by -1 and then order descending. It will keep the order you're expecing but put NULL last.

select *
from table
order by -rank desc
Luizgrs
  • 4,765
  • 1
  • 22
  • 28
  • Was just about to comment this. Learned it from https://stackoverflow.com/a/8174026/1193304 and it's great – Chris Feb 21 '18 at 21:15
6

In Oracle, you can use NULLS FIRST or NULLS LAST: specifies that NULL values should be returned before / after non-NULL values:

ORDER BY { column-Name | [ ASC | DESC ] | [ NULLS FIRST | NULLS LAST ] }

For example:

ORDER BY date DESC NULLS LAST

Ref: http://docs.oracle.com/javadb/10.8.3.0/ref/rrefsqlj13658.html

Joaquinglezsantos
  • 1,510
  • 16
  • 26
6

If you're using MariaDB, they mention the following in the NULL Values documentation.

Ordering

When you order by a field that may contain NULL values, any NULLs are considered to have the lowest value. So ordering in DESC order will see the NULLs appearing last. To force NULLs to be regarded as highest values, one can add another column which has a higher value when the main field is NULL. Example:

SELECT col1 FROM tab ORDER BY ISNULL(col1), col1;

Descending order, with NULLs first:

SELECT col1 FROM tab ORDER BY IF(col1 IS NULL, 0, 1), col1 DESC;

All NULL values are also regarded as equivalent for the purposes of the DISTINCT and GROUP BY clauses.

The above shows two ways to order by NULL values, you can combine these with the ASC and DESC keywords as well. For example the other way to get the NULL values first would be:

SELECT col1 FROM tab ORDER BY ISNULL(col1) DESC, col1;
--                                         ^^^^
3limin4t0r
  • 19,353
  • 2
  • 31
  • 52
5
SELECT *          
FROM Employees
ORDER BY ISNULL(DepartmentId, 99999);

See this blog post.

Community
  • 1
  • 1
user3923117
  • 51
  • 1
  • 2
4

Thanks RedFilter for providing excellent solution to the bugging issue of sorting nullable datetime field.

I am using SQL Server database for my project.

Changing the datetime null value to '1' does solves the problem of sorting for datetime datatype column. However if we have column with other than datetime datatype then it fails to handle.

To handle a varchar column sort, I tried using 'ZZZZZZZ' as I knew the column does not have values beginning with 'Z'. It worked as expected.

On the same lines, I used max values +1 for int and other data types to get the sort as expected. This also gave me the results as were required.

However, it would always be ideal to get something easier in the database engine itself that could do something like:

Order by Col1 Asc Nulls Last, Col2 Asc Nulls First 

As mentioned in the answer provided by a_horse_with_no_name.

Kasim Husaini
  • 392
  • 3
  • 14
4

Solution using the "case" is universal, but then do not use the indexes.

order by case when MyDate is null then 1 else 0 end, MyDate

In my case, I needed performance.

 SELECT smoneCol1,someCol2  
 FROM someSch.someTab
 WHERE someCol2 = 2101 and ( someCol1 IS NULL ) 
  UNION   
 SELECT smoneCol1,someCol2
 FROM someSch.someTab
 WHERE someCol2 = 2101 and (  someCol1 IS NOT NULL)  
Adam111p
  • 3,469
  • 1
  • 23
  • 18
1

USE NVL function

  select * from MyTable order by NVL(MyDate, to_date('1-1-1','DD-MM-YYYY'))

Here's the alternative of NVL in most famous DBMS

Charmi
  • 594
  • 1
  • 5
  • 20
1
order by -cast([nativeDateModify] as bigint) desc
paparazzo
  • 44,497
  • 23
  • 105
  • 176