SQL Tutorial › Querying Data › ORDER BY

SQL ORDER BY

BeginnerLesson 11 of 699 min read9 queries run on MySQL 8.4

Without ORDER BY, a database returns rows in whatever order is cheapest for it, and that order can change from one run to the next. ORDER BY sorts the result so it is predictable: highest salary first, newest order first, names A to Z.

Advertisement
In this lesson
  • Sort ascending (ASC) and descending (DESC)
  • Sort by several columns to break ties
  • Sort by an expression or a SELECT alias
  • Control where NULLs go and define a custom order

ORDER BY syntax

MySQL
SELECT columnsFROM table_nameORDER BY column1 [ASC | DESC], column2 [ASC | DESC], ...;

ASC (ascending: A to Z, small to large, old to new) is the default. DESC reverses it.

Sample data

employees · 12 rows (some columns)
emp_idfirst_namedept_idsalaryhire_date
100MeeraNULL2500002015-01-05
101Asha11250002018-04-12
102Rahul1980002019-07-01
103Priya1720002021-01-18
104Karan1720002022-08-29
105Vikram21050002017-11-20
106Neha2540002022-03-14
107Arjun2480002023-06-05
108Kavya3880002020-09-09
109Rohan3450002024-01-22
110Sneha4780002019-02-25
111Amit1250002025-06-02

Sort ascending

SQL
SELECT first_name, salaryFROM employeesORDER BY salary;
ResultMySQL 8.4
first_namesalary
Amit25000
Rohan45000
Arjun48000
Neha54000
Priya72000
Karan72000
Sneha78000
Kavya88000
Rahul98000
Vikram105000
Asha125000
Meera250000
12 rows in set
How this query works, step by step
  1. FROM employees reads 12 rows.
  2. SELECT keeps two columns.
  3. ORDER BY salary sorts from the lowest salary (25,000) to the highest (250,000). ASC is implied.

Sort descending

SQL
SELECT first_name, hire_dateFROM employeesORDER BY hire_date DESC;
ResultMySQL 8.4
first_namehire_date
Amit2025-06-02
Rohan2024-01-22
Arjun2023-06-05
Karan2022-08-29
Neha2022-03-14
Priya2021-01-18
Kavya2020-09-09
Rahul2019-07-01
Sneha2019-02-25
Asha2018-04-12
Vikram2017-11-20
Meera2015-01-05
12 rows in set
How this query works, step by step
  1. DESC puts the largest value first. For dates that means the most recent.
  2. Amit, hired in June 2025, is first; Meera, hired in 2015, is last.

Sort by several columns

Sort by department, and inside each department by salary from high to low:

SQL
SELECT dept_id, first_name, salaryFROM employeesORDER BY dept_id, salary DESC;
ResultMySQL 8.4
dept_idfirst_namesalary
NULLMeera250000
1Asha125000
1Rahul98000
1Priya72000
1Karan72000
1Amit25000
2Vikram105000
2Neha54000
2Arjun48000
3Kavya88000
3Rohan45000
4Sneha78000
12 rows in set
How this query works, step by step
  1. Rows are first sorted by dept_id ascending. The CEO’s NULL department comes first, because MySQL treats NULL as smaller than any value.
  2. Rows with the same dept_id are then sorted by salary DESC.
  3. Each column has its own direction: dept_id ascending, salary descending.

Ties are common. Priya and Karan both earn 72,000; add a second key so their order is defined:

SQL
SELECT first_name, salaryFROM employeesWHERE dept_id = 1ORDER BY salary DESC, first_name;
ResultMySQL 8.4
first_namesalary
Asha125000
Rahul98000
Karan72000
Priya72000
Amit25000
5 rows in set

Sort by an expression or alias

ORDER BY runs after SELECT, so it can use a column alias:

SQL
SELECT first_name, salary, commission,       salary + IFNULL(commission, 0) AS total_payFROM employeesWHERE dept_id = 2ORDER BY total_pay DESC;
ResultMySQL 8.4
first_namesalarycommissiontotal_pay
Vikram10500012000117000
Neha54000600060000
Arjun48000450052500
3 rows in set
How this query works, step by step
  1. For each Sales employee, IFNULL(commission, 0) turns a missing commission into 0 (IFNULL).
  2. total_pay adds it to the salary.
  3. ORDER BY total_pay DESC sorts by the alias, which exists because SELECT has already run.

You can also sort by a column that is not in the SELECT list:

SQL
SELECT product_nameFROM productsORDER BY price DESCLIMIT 3;
ResultMySQL 8.4
product_name
Standing Desk
Office Chair
Mechanical Keyboard
3 rows in set

Where do NULLs go?

MySQL sorts NULL before all values in ASC and after them in DESC. To put NULLs last in an ascending sort, sort by column IS NULL first:

SQL
SELECT first_name, commissionFROM employeesORDER BY commission IS NULL, commission;
ResultMySQL 8.4
first_namecommission
Arjun4500
Neha6000
Vikram12000
MeeraNULL
AshaNULL
RahulNULL
PriyaNULL
KaranNULL
KavyaNULL
RohanNULL
SnehaNULL
AmitNULL
12 rows in set
How this query works, step by step
  1. commission IS NULL is 0 for rows with a commission and 1 for rows without.
  2. Sorting by it puts the three sales staff (0) before everyone else (1).
  3. Within the first group, commission sorts the amounts from low to high.

A custom sort order with FIELD() and CASE

Show orders by status in a business order: Pending first, then Shipped, Delivered, Cancelled:

MySQL
SELECT order_id, statusFROM ordersORDER BY FIELD(status, 'Pending', 'Shipped', 'Delivered', 'Cancelled'), order_id;
ResultMySQL 8.4
order_idstatus
1008Pending
1006Shipped
1001Delivered
1002Delivered
1003Delivered
1005Delivered
1007Delivered
1009Delivered
1010Delivered
1004Cancelled
10 rows in set
How this query works, step by step
  1. FIELD(status, ...) returns the position of the status in the list: Pending = 1, Shipped = 2, Delivered = 3, Cancelled = 4.
  2. Sorting by that number gives the business order; order_id breaks ties.

FIELD() is MySQL-specific. The portable way is a CASE expression:

SQL
SELECT order_id, statusFROM ordersORDER BY CASE status           WHEN 'Pending'   THEN 1           WHEN 'Shipped'   THEN 2           WHEN 'Delivered' THEN 3           ELSE 4         END,         order_id;
ResultMySQL 8.4
order_idstatus
1008Pending
1006Shipped
1001Delivered
1002Delivered
1003Delivered
1005Delivered
1007Delivered
1009Delivered
1010Delivered
1004Cancelled
10 rows in set
Watch out

ORDER BY 2 (sorting by column position) works, but it silently changes meaning when someone edits the SELECT list. Use column names.

Exercise: Cheapest first

List product_name, category and price, sorted by category A to Z and, within a category, from the cheapest product.

Expected resultMySQL 8.4
product_namecategoryprice
Wireless MouseElectronics799
USB-C HubElectronics1999
Mechanical KeyboardElectronics3499
Desk LampFurniture1499
Monitor ArmFurniture2799
Office ChairFurniture8999
Standing DeskFurniture18999
Gel PensStationery199
Notebook PackStationery249
9 rows in set
Hint 1

Two sort keys, both ascending.

Exercise: Newest customers

List customers from the newest joined_on date to the oldest.

Expected resultMySQL 8.4
customer_namejoined_on
Sara Thomas2025-03-02
Manoj Pillai2025-01-11
Ishita Bose2024-07-30
David Fernandes2024-05-09
Fatima Khan2024-03-21
Rohit Kumar2024-02-03
Ananya Sharma2024-01-15
7 rows in set
Hint 1

Use DESC.

Quick quiz

1. What is the default sort direction?

2. In ORDER BY dept_id, salary DESC, which column is sorted descending?

3. Where does MySQL put NULL in an ascending sort?

4. Can ORDER BY use an alias defined in SELECT?

ORDER BY FAQ

How do I sort in descending order in SQL?

Add DESC after the column: ORDER BY salary DESC. Use ASC (or nothing) for ascending.

How do I sort by multiple columns in SQL?

List them separated by commas: ORDER BY dept_id, salary DESC. Rows are sorted by the first column, and later columns break ties.

Is the row order guaranteed without ORDER BY?

No. Without ORDER BY the database may return rows in any order, and it can change when data, indexes or the query plan change.

How do I put NULL values last in MySQL?

Sort by column IS NULL first: ORDER BY commission IS NULL, commission. MySQL has no NULLS LAST clause.