KAHIBARO
Discord Login Register

10.8. ORDER BY

Why `ORDER BY` Matters

When you query a database, the default order of rows is usually undefined. You might get rows in the order they were inserted, or in some internal order, but you must never rely on that.

If you care about the order of results, you must use ORDER BY.

Rule: If you need sorted results, always use ORDER BY.
Never assume the database returns rows in a meaningful order without it.

ORDER BY lets you sort your result set by one or more columns, in ascending or descending order, and even by expressions.


Basic `ORDER BY` Syntax

The general form is:

sql
SELECT column1, column2, ...
FROM table_name
ORDER BY column_name [ASC | DESC];

Example with a simple users table:

text
users
+----+----------+-----------+--------+
| id | username | full_name | age    |
+----+----------+-----------+--------+
| 1  | alice    | Alice A   | 30     |
| 2  | bob      | Bob B     | 25     |
| 3  | carol    | Carol C   | 35     |
+----+----------+-----------+--------+

Sort by age ascending:

sql
SELECT id, username, age
FROM users
ORDER BY age;

Result:

text
+----+----------+-----+
| id | username | age |
+----+----------+-----+
| 2  | bob      | 25  |
| 1  | alice    | 30  |
| 3  | carol    | 35  |
+----+----------+-----+

Sort by age descending:

sql
SELECT id, username, age
FROM users
ORDER BY age DESC;

Sorting by Multiple Columns

You can sort by more than one column. This is useful when several rows share the same value in the first column.

Syntax:

sql
SELECT ...
FROM table_name
ORDER BY column1 [ASC | DESC],
         column2 [ASC | DESC],
         ...;

Table example:

text
employees
+----+----------+----------+--------+
| id | name     | dept     | salary |
+----+----------+----------+--------+
| 1  | Alice    | Sales    | 50000  |
| 2  | Bob      | Sales    | 55000  |
| 3  | Carol    | IT       | 60000  |
| 4  | Dave     | IT       | 60000  |
| 5  | Eve      | Sales    | 45000  |
+----+----------+----------+--------+

Sort by department ascending, then by salary descending inside each department:

sql
SELECT name, dept, salary
FROM employees
ORDER BY dept ASC, salary DESC;

Result:

text
+--------+--------+--------+
| name   | dept   | salary |
+--------+--------+--------+
| Carol  | IT     | 60000  |
| Dave   | IT     | 60000  |
| Bob    | Sales  | 55000  |
| Alice  | Sales  | 50000  |
| Eve    | Sales  | 45000  |
+--------+--------+--------+

dept controls the main grouping, salary DESC sorts within each department.

Another example, sort by salary ascending, then name ascending to stabilize the order:

sql
SELECT name, dept, salary
FROM employees
ORDER BY salary ASC, name ASC;

`ASC` vs `DESC` in Practice

You can mix ascending and descending in the same query.

Table example:

text
products
+----+----------+----------+--------+
| id | name     | category | price  |
+----+----------+----------+--------+
| 1  | Laptop   | Tech     | 900    |
| 2  | Mouse    | Tech     | 20     |
| 3  | Chair    | Office   | 70     |
| 4  | Desk     | Office   | 150    |
| 5  | Monitor  | Tech     | 200    |
+----+----------+----------+--------+

Sort by category ascending, price descending:

sql
SELECT name, category, price
FROM products
ORDER BY category ASC, price DESC;

Result:

text
+---------+----------+-------+
| name    | category | price |
+---------+----------+-------+
| Desk    | Office   | 150   |
| Chair   | Office   | 70    |
| Laptop  | Tech     | 900   |
| Monitor | Tech     | 200   |
| Mouse   | Tech     | 20    |
+---------+----------+-------+

If you omit ASC or DESC, SQL uses ascending by default:

sql
SELECT name, price
FROM products
ORDER BY price;          -- same as ORDER BY price ASC

Sorting by Column Position

You can also sort by the position of a column in the SELECT list.

Syntax:

sql
SELECT col1, col2, col3
FROM table_name
ORDER BY 2, 3 DESC;

Here, 2 means ordered by the second selected column, and 3 DESC means third selected column in descending order.

Example:

sql
SELECT name, category, price
FROM products
ORDER BY 2, 3 DESC;

This orders by category (the second selected column), and then by price (the third) descending inside each category.

Recommendation: Sorting by column position works, but using column names is clearer and less error prone.
Use column positions only when you have a strong reason, such as quick ad hoc queries.


Sorting With Expressions

You are not limited to column names in ORDER BY. You can sort by expressions and calculated values.

Common examples:

Example: Sorting by a Computed Column

Table:

text
orders
+----+----------+----------+--------+
| id | item     | quantity | price  |
+----+----------+----------+--------+
| 1  | Pen      | 10       | 1.5    |
| 2  | Notebook | 3        | 4.0    |
| 3  | Bag      | 1        | 25.0   |
+----+----------+----------+--------+

Sort by total cost (quantity times price):

sql
SELECT id, item, quantity, price, quantity * price AS total_cost
FROM orders
ORDER BY quantity * price DESC;

Result:

text
+----+----------+----------+-------+------------+
| id | item     | quantity | price | total_cost |
+----+----------+----------+-------+------------+
| 3  | Bag      | 1        | 25.0  | 25.0       |
| 2  | Notebook | 3        | 4.0   | 12.0       |
| 1  | Pen      | 10       | 1.5   | 15.0       |
+----+----------+----------+-------+------------+

Note: The order of id 1 and 2 here will depend on the actual computed totals. Always check your math.

Example: Using the Alias in `ORDER BY`

Many databases let you use the alias defined in the SELECT list:

sql
SELECT id, item, quantity * price AS total_cost
FROM orders
ORDER BY total_cost DESC;

This is easier to read than repeating the expression.

Example: Sorting With `CASE`

Suppose you have priorities: "high", "medium", "low". You want "high" first, then "medium", then "low", even though alphabetically "high" comes before "low" and "medium".

text
tasks
+----+---------+----------+
| id | title   | priority |
+----+---------+----------+
| 1  | Task A  | low      |
| 2  | Task B  | high     |
| 3  | Task C  | medium   |
+----+---------+----------+

Custom order with CASE:

sql
SELECT id, title, priority
FROM tasks
ORDER BY
  CASE priority
    WHEN 'high' THEN 1
    WHEN 'medium' THEN 2
    WHEN 'low' THEN 3
    ELSE 4
  END;

Result:

text
+----+---------+----------+
| id | title   | priority |
+----+---------+----------+
| 2  | Task B  | high     |
| 3  | Task C  | medium   |
| 1  | Task A  | low      |
+----+---------+----------+

This pattern is common when you need custom business ordering.


Sorting With `NULL` Values

When your data contains NULL, databases must decide where to place those rows in an ordered list.

By default:

To control this, you can usually use NULLS FIRST or NULLS LAST in ORDER BY.

Table:

text
users
+----+----------+------+
| id | name     | age  |
+----+----------+------+
| 1  | Alice    | 30   |
| 2  | Bob      | NULL |
| 3  | Carol    | 25   |
| 4  | Dave     | NULL |
+----+----------+------+

Ascending by age, with nulls last:

sql
SELECT id, name, age
FROM users
ORDER BY age ASC NULLS LAST;

Possible result:

text
+----+-------+------+
| id | name  | age  |
+----+-------+------+
| 3  | Carol | 25   |
| 1  | Alice | 30   |
| 2  | Bob   | NULL |
| 4  | Dave  | NULL |
+----+-------+------+

Descending by age, with nulls first:

sql
SELECT id, name, age
FROM users
ORDER BY age DESC NULLS FIRST;

Important: Handling NULL correctly is critical.
Always think about where rows with missing values should appear in sorted results, and use NULLS FIRST or NULLS LAST if needed.

If your database does not support NULLS FIRST / LAST, you can simulate it with expressions, for example:

sql
ORDER BY (age IS NULL), age

Since (age IS NULL) is false (0) or true (1), non null ages come first.


`ORDER BY` With `LIMIT` (Top N Results)

ORDER BY becomes especially powerful when combined with LIMIT (or TOP in some SQL engines) to get only the first N rows.

Common patterns:

Example table:

text
posts
+----+-----------------+---------------------+
| id | title           | created_at          |
+----+-----------------+---------------------+
| 1  | Hello World     | 2023-01-01 10:00:00 |
| 2  | Second Post     | 2023-01-02 09:00:00 |
| 3  | Another Post    | 2023-01-03 12:00:00 |
| 4  | Newest Post     | 2023-01-04 08:00:00 |
+----+-----------------+---------------------+

Latest 2 posts:

sql
SELECT id, title, created_at
FROM posts
ORDER BY created_at DESC
LIMIT 2;

Result:

text
+----+-------------+---------------------+
| id | title       | created_at          |
+----+-------------+---------------------+
| 4  | Newest Post | 2023-01-04 08:00:00 |
| 3  | Another Post| 2023-01-03 12:00:00 |
+----+-------------+---------------------+

Top 3 most expensive products:

sql
SELECT name, price
FROM products
ORDER BY price DESC
LIMIT 3;

This pattern is extremely common in backend development, for example when you display "Top 10" lists or recent activity.


Using `ORDER BY` With `GROUP BY` and Aggregates

When you use GROUP BY, you often want to sort by an aggregate value, such as COUNT, SUM, or AVG.

Table:

text
sales
+----+----------+--------+
| id | product  | amount |
+----+----------+--------+
| 1  | Pen      | 10     |
| 2  | Pen      | 5      |
| 3  | Notebook | 7      |
| 4  | Bag      | 20     |
| 5  | Notebook | 8      |
+----+----------+--------+

Total sales per product, highest first:

sql
SELECT product, SUM(amount) AS total_amount
FROM sales
GROUP BY product
ORDER BY total_amount DESC;

Result:

text
+----------+--------------+
| product  | total_amount |
+----------+--------------+
| Bag      | 20           |
| Notebook | 15           |
| Pen      | 15           |
+----------+--------------+

If there is a tie in total_amount, the order between those rows is undefined unless you add a secondary sort:

sql
ORDER BY total_amount DESC, product ASC;

Common Patterns and Examples

Here is a compact table of common sorting tasks and how to write them.


GoalExample ORDER BY clause
Alphabetical A to ZORDER BY name ASC
Alphabetical Z to AORDER BY name DESC
Lowest price firstORDER BY price ASC
Highest price firstORDER BY price DESC
Newest record firstORDER BY created_at DESC
Oldest record firstORDER BY created_at ASC
Sort by multiple fieldsORDER BY category ASC, price DESC
Custom priority orderORDER BY CASE priority WHEN 'high' THEN 1 ... END
Shortest name firstORDER BY LENGTH(name) ASC
Longest name firstORDER BY LENGTH(name) DESC
Non null values firstORDER BY (age IS NULL), age ASC
Nulls last, descending scoreORDER BY score DESC NULLS LAST
Top N by scoreORDER BY score DESC LIMIT 10
Sort by aggregate (most orders)ORDER BY COUNT(*) DESC with GROUP BY customer_id

Summary

Views: 8

Comments

Please login to add a comment.

Don't have an account? Register now!