How to Write an ORDER BY Clause with Exceptions using SQL

In SQL, the ORDER BY clause is commonly used to order the results of a query. It allows you to select one or more columns to order the results, and in most cases, it’s probably all you need.

But what if you need to make an exception?

What if you want the results to be ordered alphabetically, except for one row? Or several rows?

Or perhaps you simply want to put any NULL values to the end, while ordering the non-NULL results.

Either way, there’s a neat trick you can use that will enable you to do this. And the good part is, it’s simple.

You can cater for all of the above scenarios by adding a CASE expression to your ORDER BY clause.

Example 1 – Move “Other” to the Bottom

Suppose we run the following query against a table containing music genres.

SELECT Genre 
FROM MusicGenres
ORDER BY Genre ASC;

Result:

+---------+
| Genre   |
|---------|
| Blues   |
| Country |
| Hip Hop |
| Jazz    |
| Metal   |
| Other   |
| Pop     |
| Rap     |
| Rock    |
+---------+

In this case, we order the results by the Genre column, in ascending order.

This is fine except for one thing. The genre called Other. Wouldn’t it be nice if we could move Other to the bottom?

We can achieve this with the CASE expression. Therefore, we can take the above query, and modify its ORDER BY clause as follows.

SELECT Genre
FROM MusicGenres
ORDER BY 
    CASE Genre
        WHEN 'Other' THEN 1
        ELSE 0
    END
    ASC, Genre ASC;

Result:

+---------+
| Genre   |
|---------|
| Blues   |
| Country |
| Hip Hop |
| Jazz    |
| Metal   |
| Pop     |
| Rap     |
| Rock    |
| Other   |
+---------+

Example 2 – Move NULLs to the Bottom

If your table happens to contain any of them pesky NULL values, you’ll find that they’ll insist on staying at the top when you order in ascending order.

Once again, CASE expression to the rescue!

Let’s imagine that the above table contains a couple NULL values. And when we run our query, it looks more like this:

SELECT Genre
FROM MusicGenres
ORDER BY 
    CASE Genre
        WHEN 'Other' THEN 1
        ELSE 0
    END
    ASC, Genre ASC;

Result:

+---------+
| Genre   |
|---------|
| NULL    |
| NULL    |
| Blues   |
| Hip Hop |
| Jazz    |
| Metal   |
| Pop     |
| Rock    |
| Other   |
+---------+

So now we want to move the NULL values to the bottom – even lower than Other.

We can do that with the following query.

SELECT Genre
FROM MusicGenres
ORDER BY 
    CASE
        WHEN Genre IS NULL THEN 2
        WHEN Genre = 'Other' THEN 1
        ELSE 0
    END
    ASC, Genre ASC;

Result:

+---------+
| Genre   |
|---------|
| Blues   |
| Hip Hop |
| Jazz    |
| Metal   |
| Pop     |
| Rock    |
| Other   |
| NULL    |
| NULL    |
+---------+

In this example, we used a different CASE format. In this example we used a searched CASE expression, as opposed to the previous example which, used a simple CASE expression.

The searched CASE expression evaluates a set of Boolean expressions to determine the result.

The simple CASE expression, on the other hand, compares an expression to a set of simple expressions to determine the result.

The simple CASE expression has an input expression next to the CASE keyword, whereas, the searched CASE expression doesn’t.

Example 3 – Fix Certain Rows to the Top

Now imagine we want to have one or more rows that are always at the top of the results, regardless of where they fit within the ordering of the wider results.

For example:

SELECT * FROM vAlbums
ORDER BY ArtistName ASC, AlbumName ASC;

Result:

+------------------------+--------------------------+---------+
| ArtistName             | AlbumName                | Genre   |
|------------------------+--------------------------+---------|
| AC/DC                  | Powerage                 | Rock    |
| Allan Holdsworth       | All Night Wrong          | Jazz    |
| Allan Holdsworth       | The Sixteen Men of Tain  | Jazz    |
| Buddy Rich             | Big Swing Face           | Jazz    |
| Devin Townsend         | Casualties of Cool       | Rock    |
| Devin Townsend         | Epicloud                 | Rock    |
| Devin Townsend         | Ziltoid the Omniscient   | Rock    |
| Iron Maiden            | Killers                  | Rock    |
| Iron Maiden            | No Prayer for the Dying  | Rock    |
| Iron Maiden            | Piece of Mind            | Rock    |
| Iron Maiden            | Powerslave               | Rock    |
| Iron Maiden            | Somewhere in Time        | Rock    |
| Jim Reeves             | Singing Down the Lane    | Country |
| Michael Learns to Rock | Blue Night               | Pop     |
| Michael Learns to Rock | Eternity                 | Pop     |
| Michael Learns to Rock | Scandinavia              | Pop     |
| The Script             | No Sound Without Silence | Pop     |
| Tom Jones              | Along Came Jones         | Pop     |
| Tom Jones              | Long Lost Suitcase       | Pop     |
| Tom Jones              | Praise and Blame         | Pop     |
+------------------------+--------------------------+---------+

These results are ordered by ArtistName, and then by AlbumName.

But the record company has decided that they want to do a special promotion for Tom Jones. And so they want Tom Jones to appear at the top of the results, but then all the remaining results are to be ordered as is – alphabetically by the artist name, then by the album name.

In this case, we can do the following:

SELECT * FROM vAlbums
ORDER BY 
    CASE ArtistName
        WHEN 'Tom Jones' THEN 0
        ELSE 1
    END,
    ArtistName ASC, AlbumName ASC;

Result:

+------------------------+--------------------------+---------+
| ArtistName             | AlbumName                | Genre   |
|------------------------+--------------------------+---------|
| Tom Jones              | Along Came Jones         | Pop     |
| Tom Jones              | Long Lost Suitcase       | Pop     |
| Tom Jones              | Praise and Blame         | Pop     |
| AC/DC                  | Powerage                 | Rock    |
| Allan Holdsworth       | All Night Wrong          | Jazz    |
| Allan Holdsworth       | The Sixteen Men of Tain  | Jazz    |
| Buddy Rich             | Big Swing Face           | Jazz    |
| Devin Townsend         | Casualties of Cool       | Rock    |
| Devin Townsend         | Epicloud                 | Rock    |
| Devin Townsend         | Ziltoid the Omniscient   | Rock    |
| Iron Maiden            | Killers                  | Rock    |
| Iron Maiden            | No Prayer for the Dying  | Rock    |
| Iron Maiden            | Piece of Mind            | Rock    |
| Iron Maiden            | Powerslave               | Rock    |
| Iron Maiden            | Somewhere in Time        | Rock    |
| Jim Reeves             | Singing Down the Lane    | Country |
| Michael Learns to Rock | Blue Night               | Pop     |
| Michael Learns to Rock | Eternity                 | Pop     |
| Michael Learns to Rock | Scandinavia              | Pop     |
| The Script             | No Sound Without Silence | Pop     |
+------------------------+--------------------------+---------+