CASE Expressions, for complex Order Bys in SQL

So here’s the problem I was having:

I wanted to order a set of data by Date End, with ‘date_end’ a datetime column in our database.
However, the data could also be 00-00-0000 00:00:00 – which represents ‘Present’, where there is no end date.

Heres some data as an example:

id date_start date_end
A 2010-02-01 00:00:00 2011-02-01 00:00:00
B 2011-02-01 00:00:00 2012-02-01 00:00:00
C 2013-02-01 00:00:00 0000-00-00 00:00:00
D 2009-02-01 00:00:00 2010-02-01 00:00:00
E 2008-02-01 00:00:00 2009-02-01 00:00:00

A standard SQL query with “ORDER BY date_end DESC” would return:

id date_start date_end
B 2011-02-01 00:00:00 2012-02-01 00:00:00
A 2010-02-01 00:00:00 2011-02-01 00:00:00
D 2009-02-01 00:00:00 2010-02-01 00:00:00
E 2008-02-01 00:00:00 2009-02-01 00:00:00
C 2013-02-01 00:00:00 0000-00-00 00:00:00

To get the Present one at the top, we can use the Case expression.

“CASE date_end WHEN 00-00-00 00:00:00 THEN 1 ELSE 2 END”

So CASE date_end is the column we have selected. WHEN selects the value we are looking for, and then THEN and ELSE assign values to the rows based on whether they match the value we are looking for. So we can visualise the result as something like this:

id date_start date_end case
A 2010-02-01 00:00:00 2011-02-01 00:00:00 2
B 2011-02-01 00:00:00 2012-02-01 00:00:00 2
C 2013-02-01 00:00:00 0000-00-00 00:00:00 1
D 2009-02-01 00:00:00 2010-02-01 00:00:00 2
E 2008-02-01 00:00:00 2009-02-01 00:00:00 2

So now we can order by our case statement, and then by date_end as a secondary clause.

“ORDER BY CASE date_end WHEN 00-00-00 00:00:00 THEN 1 ELSE 2 END, date_end DESC”

Which gives us our dates ordered by date with most recent (present) first:

id date_start date_end
C 2013-02-01 00:00:00 0000-00-00 00:00:00
B 2011-02-01 00:00:00 2012-02-01 00:00:00
A 2010-02-01 00:00:00 2011-02-01 00:00:00
D 2009-02-01 00:00:00 2010-02-01 00:00:00
E 2008-02-01 00:00:00 2009-02-01 00:00:00

Finally, as we are using Laravel as our PHP Framework, we can use Laravel’s Fluent Query Builderalongside a Raw Query.

DB::table(‘history’)
->order_by(DB::raw(‘case date_end when 0 then 1 else 2 end’))
->order_by(‘date_end’, ‘desc’);

Popular Reads

Subscribe

Keep up to date

Please provide your email address
Please provide your name
Please provide your name
No thanks