SQL multiple column ordering
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
Sorting by more than one column is one of the most common SQL tasks because real datasets usually need tie-breakers. A report might be grouped by department, then alphabetized by last name, then sorted by hire date inside those groups. SQL handles this with a single ORDER BY clause, but the order of columns and the handling of NULL values matter more than many people expect.
How Multiple-Column Ordering Works
SQL evaluates the ORDER BY list from left to right. The first column is the primary sort key. If two rows tie on that column, SQL compares the second column. If they still tie, it compares the third, and so on.
Basic syntax:
This means:
- group rows by
departmentalphabetically - within each department, sort by
last_name - if two people share the same last name, put the higher salary first
That left-to-right precedence is the core rule to remember.
A Practical Example
Suppose you want to list orders so the newest orders for each customer appear first, while customers themselves are sorted alphabetically.
If the data contains:
the result order becomes:
The first key keeps all of Alice’s rows together. The second key determines the order inside Alice’s group.
Mix Ascending and Descending Safely
Each sort key can have its own direction.
This is a common reporting pattern:
- group by category
- show highest-rated items first
- break remaining ties by lower price
Do not assume DESC applies to all later columns. It only applies to the column it directly follows.
Use Extra Tie-Breakers for Stable Results
If the ordered columns still contain duplicates, row order may be nondeterministic from one execution to another. That is not always wrong, but it can make pagination and testing harder.
Example:
If two rows share the same status and identical created_at, their relative order is unspecified. A safer query adds a final unique key:
That final tie-breaker makes the output stable.
NULL Handling Differs Across Databases
NULL sorting is one of the most database-specific parts of ordering. Some engines sort NULL values first in ascending order, others last. PostgreSQL and Oracle support explicit control:
If your database does not support NULLS FIRST or NULLS LAST, use an expression:
Be careful here. A query that looks fine on one database can produce a different order on another because of NULL behavior alone.
Performance and Index Considerations
Sorting is not just a presentation concern. It also affects performance. When the ORDER BY columns line up with an index, the database may be able to avoid an expensive explicit sort.
For example, this index may help:
That does not guarantee the index will be used, because filtering, joins, and query shape still matter, but it gives the optimizer a useful option.
As a rule:
- sort only by columns you actually need
- add deterministic tie-breakers when output order matters
- review execution plans for expensive sorts on large tables
Common Pitfalls
The first common mistake is assuming the second ordered column affects the whole result set. It only breaks ties created by the first column.
Another issue is forgetting about nondeterministic order when ties remain. This often shows up in paginated APIs, where records can appear on different pages between requests.
NULL handling is also a major source of bugs, especially when SQL moves between PostgreSQL, MySQL, SQL Server, and SQLite.
Finally, do not use column positions such as ORDER BY 1, 3 DESC unless there is a strong reason. It is legal SQL, but it becomes harder to read and easier to break during refactoring.
Summary
- SQL applies multiple sort keys from left to right.
- Each column in
ORDER BYcan have its ownASCorDESCdirection. - Add a unique final tie-breaker when you need stable, deterministic output.
- Be explicit about
NULLordering when portability matters. - Matching indexes can make large ordered queries much faster.
Related reading
- sql multithreading application select and delete from a table
- SQL MySQL vs NoSQL CouchDB
- SQL order string as number
- SQL query return data from multiple tables
- SQLite - ORDER BY RAND
- Stability of quicksort partitioning approach
- SQL Server replication for 70 databases with transformation in a small time window
- SQL split values to multiple rows

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.