SQL ORDER BY: ASC, DESC and Multiple Columns
ORDER BY sorts the rows of a query result. Without it, a database returns rows in whatever order is convenient for it, and that order can change. Add ORDER BY whenever the order matters: highest first, newest first, A to Z.
What Does ORDER BY Do?
The most expensive products first:
SELECT name, category, price
FROM products
ORDER BY price DESC
LIMIT 5;
▶ Run this query in the SQL Playground
| name | category | price |
|---|---|---|
| Single Origin Coffee 500g | Food & Beverage | 1991.75 |
| Succulent Plant Set | Home & Garden | 1990.16 |
| The Manager's Path | Books | 1979.28 |
| 2000A Jump Starter Pack | Automotive | 1948.86 |
| Japanese Green Tea 50 bags | Food & Beverage | 1937.51 |
SELECT columns
FROM table
ORDER BY column_1 [ASC | DESC], column_2 [ASC | DESC], ...;
ORDER BY comes at the end of the query (only LIMIT follows it) and is applied to the finished result, after WHERE, GROUP BY and HAVING.
ASC and DESC
ASC (ascending) puts the lowest value first and is the default, so ORDER BY price and ORDER BY price ASC are the same. DESC (descending) reverses it.
SELECT name, price
FROM products
ORDER BY price
LIMIT 5;
▶ Run this query in the SQL Playground
| name | price |
|---|---|
| Sleeping Bag -10C | 35.76 |
| 4K Dual Dash Camera | 73.64 |
| The Manager's Path | 89.76 |
| Artisan Hot Sauce Trio | 104.33 |
| Smart Thermostat | 115.69 |
| Type | ASC | DESC |
|---|---|---|
| Numbers | 1, 2, 3 | 3, 2, 1 |
| Text | A to Z | Z to A |
| Dates | Oldest first | Newest first |
Sorting by Multiple Columns
List several columns and each later one breaks ties in the earlier ones. Employees by department A to Z, and within each department by salary, highest first:
SELECT department, first_name, last_name, salary
FROM employees
ORDER BY department ASC, salary DESC
LIMIT 8;
▶ Run this query in the SQL Playground
| department | first_name | last_name | salary |
|---|---|---|---|
| Customer Success | Nancy | Thompson | 203999 |
| Customer Success | Maria | Garcia | 191120 |
| Customer Success | Barbara | Baker | 188280 |
| Customer Success | Melissa | Thomas | 178391 |
| Customer Success | Dorothy | Campbell | 165118 |
| Customer Success | Charles | Allen | 162901 |
| Customer Success | Sarah | Ramirez | 152154 |
| Customer Success | Edward | Ramirez | 137737 |
Each column has its own direction. ORDER BY department, salary DESC means department ascending (the default) and salary descending; the DESC applies only to the column it follows.
id at the end fixes it.Sorting Dates and Text
Dates
Newest orders first is one of the most common sorts:
SELECT id, order_date, status, total
FROM orders
ORDER BY order_date DESC, id DESC
LIMIT 5;
▶ Run this query in the SQL Playground
| id | order_date | status | total |
|---|---|---|---|
| 70 | 2024-12-24 | pending | 2104.22 |
| 171 | 2024-12-23 | delivered | 2162.1 |
| 155 | 2024-12-19 | cancelled | 110.6 |
| 128 | 2024-12-13 | refunded | 370.05 |
| 169 | 2024-12-12 | delivered | 1308.16 |
In the Playground dates are stored as text in YYYY-MM-DD form, which sorts correctly as text. A format such as DD/MM/YYYY would not: "02/01/2024" would sort before "15/12/2023".
Text and upper/lower case
SELECT DISTINCT last_name
FROM users
ORDER BY last_name
LIMIT 6;
▶ Run this query in the SQL Playground
| last_name |
|---|
| Adams |
| Allen |
| Anderson |
| Baker |
| Brown |
| Campbell |
Whether case matters depends on the database's collation. SQLite and PostgreSQL (with most collations) sort all capital letters before lowercase ones, so "Banana" comes before "apple". MySQL and SQL Server usually ignore case. To sort without regard to case everywhere, write ORDER BY LOWER(last_name).
Sorting by Aliases, Expressions and Aggregates
ORDER BY can use a column alias from SELECT, because it runs after SELECT. Here the products are sorted by their margin, a calculated column:
SELECT name, price, cost,
ROUND(price - cost, 2) AS margin
FROM products
ORDER BY margin DESC
LIMIT 5;
▶ Run this query in the SQL Playground
| name | price | cost | margin |
|---|---|---|---|
| Succulent Plant Set | 1990.16 | 616.95 | 1373.21 |
| Single Origin Coffee 500g | 1991.75 | 657.28 | 1334.47 |
| Japanese Green Tea 50 bags | 1937.51 | 620 | 1317.51 |
| Waterproof Hiking Boots | 1769.01 | 566.08 | 1202.93 |
| Play Kitchen Deluxe | 1786.38 | 589.51 | 1196.87 |
With GROUP BY, ORDER BY sorts the groups. Departments by total salary cost, highest first:
SELECT department,
COUNT(*) AS employees,
SUM(salary) AS total_salary
FROM employees
GROUP BY department
ORDER BY total_salary DESC;
▶ Run this query in the SQL Playground
| department | employees | total_salary |
|---|---|---|
| Customer Success | 15 | 2012099 |
| Legal | 16 | 1805856 |
| Operations | 13 | 1649429 |
| Marketing | 13 | 1613441 |
| HR | 12 | 1489813 |
| Engineering | 11 | 1441308 |
| Design | 10 | 1339649 |
| Sales | 11 | 1285822 |
| Finance | 10 | 1214710 |
| Product | 9 | 1072374 |
You can also sort by a column that is not in SELECT, such as SELECT first_name FROM employees ORDER BY hire_date. The exception is SELECT DISTINCT, where most databases only allow ORDER BY on the selected columns.
A custom order with CASE
SELECT status, COUNT(*) AS orders
FROM orders
GROUP BY status
ORDER BY CASE status
WHEN 'pending' THEN 1
WHEN 'processing' THEN 2
WHEN 'shipped' THEN 3
WHEN 'delivered' THEN 4
ELSE 5
END;
▶ Run this query in the SQL Playground
| status | orders |
|---|---|
| pending | 23 |
| processing | 28 |
| shipped | 21 |
| delivered | 82 |
| cancelled | 27 |
| refunded | 19 |
Where NULLs Go
Databases disagree on where NULL sorts. SQLite, MySQL and SQL Server treat NULL as the lowest value, so NULLs come first in ascending order. PostgreSQL and Oracle treat it as the highest, so they come last:
SELECT id, status, shipped_date
FROM orders
ORDER BY shipped_date
LIMIT 4;
▶ Run this query in the SQL Playground
| id | status | shipped_date |
|---|---|---|
| 1 | cancelled | NULL |
| 4 | processing | NULL |
| 7 | refunded | NULL |
| 9 | cancelled | NULL |
SQLite (3.30+), PostgreSQL and Oracle let you choose with NULLS FIRST or NULLS LAST:
SELECT id, status, shipped_date
FROM orders
ORDER BY shipped_date NULLS LAST
LIMIT 4;
▶ Run this query in the SQL Playground
| id | status | shipped_date |
|---|---|---|
| 66 | delivered | 2023-01-08 |
| 196 | delivered | 2023-01-08 |
| 163 | shipped | 2023-01-09 |
| 181 | shipped | 2023-01-18 |
MySQL and SQL Server do not support NULLS LAST; sort on a flag first instead: ORDER BY shipped_date IS NULL, shipped_date.
ORDER BY and Performance
| Tip | Why |
|---|---|
| Sort only when you need to | Sorting means reading all qualifying rows before returning the first one |
| Use LIMIT for top-N queries | The database can keep only the best N rows while sorting |
| An index on the ORDER BY columns can remove the sort | Rows can be read in index order |
| Avoid functions on the sort column when an index exists | ORDER BY LOWER(name) cannot use a plain index on name |
Common ORDER BY Mistakes
Five errors and how to avoid them.
1. Relying on the default order
SELECT * FROM orders LIMIT 10;
SELECT * FROM orders
ORDER BY order_date DESC, id DESC
LIMIT 10;
Without ORDER BY, "the first 10 rows" is whatever the database finds first, and that can change after an update or on another server.
2. ORDER BY in the wrong place
SELECT * FROM orders
ORDER BY total DESC
WHERE status = 'delivered';
SELECT * FROM orders
WHERE status = 'delivered'
ORDER BY total DESC;
The clause order is fixed: SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT.
3. Expecting DESC to apply to every column
ORDER BY department, salary DESC
-- meant: both descending
ORDER BY department DESC, salary DESC
Each column takes its own ASC or DESC; the default for the others is ASC.
4. ORDER BY column position
SELECT name, price FROM products
ORDER BY 2 DESC;
SELECT name, price FROM products
ORDER BY price DESC;
ORDER BY 2 means "the second selected column". Add a column at the front and the sort silently changes.
5. Sorting dates stored in the wrong format
-- dates stored as 'DD/MM/YYYY'
ORDER BY order_date_text
-- dates stored as 'YYYY-MM-DD' or a real DATE type
ORDER BY order_date
Text sorts character by character. Only year-month-day order (or a real date type) sorts chronologically.
Practice ORDER BY Queries
5 exercises on the real Playground tables.
Write each query yourself first. Every solution has been run against the Playground database.
-
1Easy List the 5 most recently hired employees. Table:
employeesShow solution
SELECT first_name, last_name, hire_date FROM employees ORDER BY hire_date DESC LIMIT 5;▶ Run this query in the SQL Playground
DESC on a date puts the newest first.
-
2Easy List the first 6 users alphabetically by last name, then first name. Table:
usersShow solution
SELECT last_name, first_name, city FROM users ORDER BY last_name, first_name LIMIT 6;▶ Run this query in the SQL Playground
first_name breaks ties between users with the same last name.
-
3Medium Show the 5 best-rated products, and among equal ratings the ones with the most reviews first. Table:
productsShow solution
SELECT name, rating, review_count FROM products ORDER BY rating DESC, review_count DESC LIMIT 5;▶ Run this query in the SQL Playground
Two descending sorts: rating first, review_count as the tie-breaker.
-
4Medium Show revenue per order status, highest first. Table:
ordersShow solution
SELECT status, ROUND(SUM(total), 2) AS revenue FROM orders GROUP BY status ORDER BY revenue DESC;▶ Run this query in the SQL Playground
ORDER BY can use the alias of the aggregate.
-
5Medium List 6 orders with their shipped date, showing shipped orders first (newest shipment first) and unshipped orders last. Table:
ordersShow solution
SELECT id, status, shipped_date FROM orders ORDER BY shipped_date IS NULL, shipped_date DESC LIMIT 6;▶ Run this query in the SQL Playground
shipped_date IS NULL is 0 for shipped orders and 1 for the rest, so it sorts unshipped orders to the end in any database.
📝 Quiz — ORDER BY
Test your understanding · 0/6 answered
What does ORDER BY do in SQL?
It runs last and arranges the finished result in ascending (default) or descending order.
What is the default direction of ORDER BY price?
ORDER BY price is the same as ORDER BY price ASC.
Which query shows the most expensive products first?
Highest first means DESC. SORT BY is not SQL.
What does ORDER BY salary DESC, last_name ASC do?
The first column decides; the second breaks ties.
Where does ORDER BY go in a query?
SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT.
Which query shows customers by total spend, highest first?
Group per customer, alias the sum, then sort by the alias.
ORDER BY Interview Questions
Q1. Is the order of rows guaranteed without ORDER BY?
No. The database may return rows in any order, and it can change with indexes, updates or parallel execution. Only ORDER BY guarantees an order.
Q2. Why can ORDER BY use a SELECT alias but WHERE cannot?
ORDER BY is processed after SELECT, so the alias exists; WHERE is processed before SELECT.
Q3. Where do NULLs sort?
First in ascending order in SQLite, MySQL and SQL Server; last in PostgreSQL and Oracle. SQLite, PostgreSQL and Oracle support NULLS FIRST / NULLS LAST; MySQL and SQL Server need a trick such as ORDER BY col IS NULL, col.
Q4. How do you make pagination stable?
Sort by columns that together are unique, for example ORDER BY order_date DESC, id DESC, so rows with equal dates always come in the same order.
Q5. Does ORDER BY slow a query down?
It can, because the database has to sort all qualifying rows. An index on the sort columns, or LIMIT for top-N queries, reduces the cost.
Frequently Asked Questions
What does ORDER BY do in SQL?
ORDER BY sorts the rows of the result. By default it sorts ascending (lowest to highest, A to Z, oldest to newest). Add DESC after a column to sort descending.
Is ASC the default sort order in SQL ORDER BY?
Yes. ORDER BY column is the same as ORDER BY column ASC. You only need to write DESC when you want the highest value first.
What is the difference between ASC and DESC in ORDER BY?
ASC sorts from the lowest value to the highest: 1, 2, 3 and A, B, C. DESC reverses it. Reports often use DESC to show the top values first.
Can you ORDER BY multiple columns?
Yes. ORDER BY col1 DESC, col2 ASC sorts by col1 first and uses col2 to order rows where col1 is equal. Each column can have its own direction.
Where does ORDER BY go in the clause order?
Near the end: SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, and then LIMIT. It sorts the finished result.
Can you use ORDER BY with GROUP BY?
Yes. GROUP BY builds the groups and ORDER BY sorts them, for example GROUP BY department ORDER BY SUM(salary) DESC.
Can ORDER BY use a column alias?
Yes, in all major databases. If you write SELECT SUM(total) AS revenue you can then write ORDER BY revenue DESC, because ORDER BY is processed after SELECT.
Does ORDER BY work on text columns?
Yes. ORDER BY name sorts A to Z and ORDER BY name DESC sorts Z to A. Whether upper and lower case are treated the same depends on the database's collation: SQLite and PostgreSQL usually distinguish them, MySQL and SQL Server usually do not.
Can ORDER BY sort date columns?
Yes. Dates sort like numbers: ASC is oldest first, DESC newest first. If dates are stored as text, they must be in YYYY-MM-DD form to sort correctly.
What is the difference between ORDER BY and GROUP BY?
GROUP BY combines rows into groups for aggregation and changes the number of rows. ORDER BY only rearranges rows and never changes how many there are.
How do NULL values sort in ORDER BY?
SQLite, MySQL and SQL Server put NULLs first in ascending order; PostgreSQL and Oracle put them last. SQLite, PostgreSQL and Oracle accept NULLS FIRST or NULLS LAST to choose.
Can you ORDER BY a column not in SELECT?
Yes, in most cases you can sort by any column of the tables in FROM. With SELECT DISTINCT, most databases only allow sorting by the selected columns.
Does ORDER BY affect performance?
Yes. Sorting needs all qualifying rows before the first one can be returned. An index on the ORDER BY columns can avoid the sort, and LIMIT reduces the work for top-N queries.
Can you use ORDER BY with DISTINCT?
Yes. SELECT DISTINCT last_name FROM users ORDER BY last_name works. Sort by the selected columns, because other columns are not allowed with DISTINCT in most databases.
What does ORDER BY 1 mean in SQL?
It sorts by the first column in the SELECT list. It is valid but fragile: change the SELECT list and the sort changes. Prefer column names.
How do you get the top N rows in SQL?
Combine ORDER BY with LIMIT in MySQL, PostgreSQL and SQLite: SELECT * FROM products ORDER BY price DESC LIMIT 10. SQL Server uses TOP 10, and the standard form is FETCH FIRST 10 ROWS ONLY.