SQL ORDER BY and LIMIT give you control over the order and size of your query results. You wrote a perfectly valid SELECT statement, hit run, and got back hundreds of rows in no particular order.
You Finally Ran Your First Query — Now the Results Are a Mess Sound familiar? Raw database output is like a shuffled deck of cards — technically complete, but useless until you put it in order.
That is where ORDER BY and LIMIT come in. These two clauses give you control over what you see and how much of it you see. Whether you are building a "Top 10" leaderboard, paginating an API response, or simply making sense of your data, sorting and limiting are skills you will use in virtually every SQL query you write.
Table of Contents
- How ORDER BY Works
- Sorting by Multiple Columns
- Limiting Results with LIMIT
- Pagination with LIMIT and OFFSET
- Top-N Queries and Real-World Patterns
- Quick Comparison / Cheat Sheet
- Common Mistakes to Avoid
- Practice Makes Perfect
- Summary
- FAQs
How ORDER BY Works
The ORDER BY clause sorts your result set by one or more columns. By default, it sorts in ascending order (ASC). Add DESC to reverse the direction.
Syntax:
SELECT columns
FROM table
ORDER BY column [ASC | DESC];
Let's start with a simple example. Find the 10 longest tracks in the Chinook database, sorted from longest to shortest:
SELECT Name, Milliseconds
FROM Track
ORDER BY Milliseconds DESC
LIMIT 10;
| Name | Milliseconds |
|---|---|
| Occupation / Precipice | 5286953 |
| Through a Looking Glass | 5088838 |
| Greetings from Earth, Pt. 1 | 2960293 |
| The Man With Nine Lives | 2956998 |
| Battlestar Galactica, Pt. 2 | 2956081 |
| Battlestar Galactica, Pt. 1 | 2952702 |
| Murder On the Rising Star | 2935894 |
| Battlestar Galactica, Pt. 3 | 2927802 |
| Take the Celestra | 2927677 |
| Fire in Space | 2926593 |
Notice how DESC gives us the longest tracks first. Without it, we would get the shortest tracks instead.
Tip:
ORDER BYis always one of the last clauses processed — it runs afterWHERE,GROUP BY, andHAVING. OnlyLIMITandOFFSETcome after it.
Sorting by Multiple Columns
Real-world queries often need to sort by more than one column. SQL evaluates each column in the order you list them — the second column only breaks ties in the first.
SELECT c.FirstName, c.LastName, i.Total
FROM Invoice i
JOIN Customer c ON c.CustomerId = i.CustomerId
ORDER BY i.Total DESC, c.LastName ASC
LIMIT 10;
| FirstName | LastName | Total |
|---|---|---|
| Helena | Holy | 25.86 |
| Richard | Cunningham | 23.86 |
| Luis | Rojas | 21.86 |
| Hugh | O'Brien | 21.86 |
| Ladislav | Kovacs | 21.86 |
| Julia | Barnett | 19.86 |
| Victor | Stevens | 19.86 |
| Fynn | Zimmermann | 19.86 |
| Astrid | Gruber | 18.86 |
| Mark | Taylor | 18.86 |
Here, invoices are sorted by total (highest first). When two invoices share the same total, last names break the tie alphabetically.
If you have used GROUP BY and HAVING to aggregate data, you can sort those aggregated results with ORDER BY — for example, sorting groups by their SUM() or COUNT().
Limiting Results with LIMIT
LIMIT restricts the number of rows returned. It is essential for performance and usability — you rarely want to dump an entire table to the screen.
SELECT Name, Composer, Milliseconds
FROM Track
WHERE Composer IS NOT NULL
ORDER BY Milliseconds ASC
LIMIT 5;
| Name | Composer | Milliseconds |
|---|---|---|
| É Uma Partida De Futebol | Samuel Rosa | 1071 |
| Now Sports | Jimi Hendrix | 4935 |
| A Fine Day | Robin Guthrie/Elizabeth Fraser | 5196 |
| Instinto Colectivo | Titãs | 6321 |
| Trupets Of Jericho | R. Blackmore/R. Glover/I. Paice/Roger Glover/Jon Lord | 7801 |
Without LIMIT 5, this query would return every track that has a composer — thousands of rows. Adding LIMIT keeps it manageable.
How LIMIT differs across databases:
- MySQL, PostgreSQL, SQLite:
LIMIT n - SQL Server:
SELECT TOP n ... - Oracle:
FETCH FIRST n ROWS ONLY(orROWNUMin older versions)
The concept is the same everywhere; only the syntax differs.
Pagination with LIMIT and OFFSET
When you build a paginated list — like page 2 of search results — you combine LIMIT with OFFSET. The OFFSET tells the database how many rows to skip before starting to return results.
-- Page 1: first 5 customers
SELECT CustomerId, FirstName, LastName, Country
FROM Customer
ORDER BY LastName ASC
LIMIT 5 OFFSET 0;
| CustomerId | FirstName | LastName | Country |
|---|---|---|---|
| 43 | Isabelle | Mercier | France |
| 56 | Diego | Gutierrez | Argentina |
| 37 | Fynn | Zimmermann | Germany |
| 24 | Frank | Ralston | USA |
| 46 | Hugh | O'Brien | Ireland |
-- Page 2: next 5 customers
SELECT CustomerId, FirstName, LastName, Country
FROM Customer
ORDER BY LastName ASC
LIMIT 5 OFFSET 5;
| CustomerId | FirstName | LastName | Country |
|---|---|---|---|
| 10 | Eduardo | Martins | Brazil |
| 7 | Astrid | Gruber | Austria |
| 6 | Helena | Holy | Czech Republic |
| 19 | Tim | Goyer | USA |
| 52 | Emma | Jones | United Kingdom |
The formula is straightforward:
OFFSET = (page_number - 1) * page_size
Performance warning: Large
OFFSETvalues can be slow because the database still reads and discards all the skipped rows. For high-performance pagination, consider keyset pagination (also called cursor-based pagination), where you filter using aWHEREclause on the last seen value instead of usingOFFSET.
Top-N Queries and Real-World Patterns
Combining ORDER BY and LIMIT unlocks some of the most common SQL patterns.
Top-N: Best Customers by Revenue
SELECT c.FirstName || ' ' || c.LastName AS Customer,
SUM(i.Total) AS TotalSpent
FROM Customer c
JOIN Invoice i ON c.CustomerId = i.CustomerId
GROUP BY c.CustomerId, c.FirstName, c.LastName
ORDER BY TotalSpent DESC
LIMIT 5;
| Customer | TotalSpent |
|---|---|
| Helena Holy | 49.62 |
| Richard Cunningham | 47.62 |
| Luis Rojas | 46.62 |
| Ladislav Kovacs | 45.62 |
| Hugh O'Brien | 45.62 |
This pattern — aggregate, sort, limit — is something you will use constantly for dashboards and reports. If you want to go further with ranking (like handling ties), check out our guide to SQL Window Functions where ROW_NUMBER() and RANK() give you even finer control.
Bottom-N: Least Popular Genres
SELECT g.Name AS Genre, COUNT(t.TrackId) AS TrackCount
FROM Genre g
LEFT JOIN Track t ON g.GenreId = t.GenreId
GROUP BY g.GenreId, g.Name
ORDER BY TrackCount ASC
LIMIT 5;
| Genre | TrackCount |
|---|---|
| Opera | 1 |
| Bossa Nova | 15 |
| Comedy | 17 |
| Science Fiction | 13 |
| Sci Fi & Fantasy | 26 |
Flipping DESC to ASC turns a "Top-N" into a "Bottom-N" query. The LEFT JOIN ensures genres with zero tracks still appear.
Latest Records
SELECT InvoiceId, InvoiceDate, Total
FROM Invoice
ORDER BY InvoiceDate DESC
LIMIT 5;
| InvoiceId | InvoiceDate | Total |
|---|---|---|
| 412 | 2025-12-22 | 1.99 |
| 411 | 2025-12-14 | 13.86 |
| 410 | 2025-12-09 | 8.91 |
| 409 | 2025-12-06 | 3.96 |
| 408 | 2025-12-02 | 5.94 |
Sorting by a date column in descending order is the go-to pattern for "most recent" queries.
Quick Comparison / Cheat Sheet
| Clause | Purpose | Default | Example |
|---|---|---|---|
ORDER BY col | Sort ascending | ASC | ORDER BY Name |
ORDER BY col DESC | Sort descending | — | ORDER BY Total DESC |
ORDER BY col1, col2 | Multi-column sort | Each column can be ASC/DESC | ORDER BY Country, LastName |
LIMIT n | Return first n rows | All rows | LIMIT 10 |
OFFSET n | Skip first n rows | 0 | LIMIT 10 OFFSET 20 |
ORDER BY + LIMIT | Top-N / Bottom-N | — | ORDER BY Total DESC LIMIT 5 |
LIMIT + OFFSET | Pagination | — | LIMIT 10 OFFSET 30 (page 4) |
Common Mistakes to Avoid
1. Using ORDER BY Without LIMIT in Subqueries
Most databases ignore ORDER BY inside a subquery unless it is paired with LIMIT. The outer query determines the final sort order. If you need sorted subquery results, consider using window functions or a CTE instead.
2. Relying on Default Row Order
Without an explicit ORDER BY, SQL databases return rows in no guaranteed order. The order might look consistent during development but can change with data growth, index changes, or parallel execution. Always add ORDER BY when order matters.
3. Using OFFSET for Deep Pagination
Paginating with OFFSET 100000 forces the database to scan and discard 100,000 rows before returning your page. For large datasets, switch to keyset pagination:
-- Instead of: LIMIT 10 OFFSET 100000
-- Use keyset pagination:
SELECT InvoiceId, InvoiceDate, Total
FROM Invoice
WHERE InvoiceId > 412 -- last ID from previous page
ORDER BY InvoiceId ASC
LIMIT 10;
4. Forgetting That NULL Sorts Differently Across Databases
In PostgreSQL, NULL values sort last in ascending order and first in descending order. In MySQL, NULL is treated as the lowest value. Use NULLS FIRST or NULLS LAST (where supported) to control this explicitly.
5. Sorting by Column Position Instead of Name
While ORDER BY 1 (sort by the first column) works, it makes queries fragile. If someone reorders the columns in the SELECT list, the sort silently changes. Always use column names or aliases for clarity.
Practice Makes Perfect
Reading about ORDER BY and LIMIT only gets you so far. The real learning happens when you write the queries yourself. Try these exercises on SQiLs to cement your skills:
| Exercise | What You'll Practice | Difficulty |
|---|---|---|
| Shortest Category Descriptions | Sorting by string length, combining ORDER BY with functions | Beginner |
| Premium Items from Specific Suppliers | Multi-column sorting with filtered results | Beginner |
| Oldest Employees in the Company | Sorting date columns to find earliest records | Beginner |
| Highest Revenue Order Lines | Top-N pattern with ORDER BY DESC and LIMIT | Beginner |
| Heaviest Freight Shipping Costs | Sorting numeric data to find extremes | Beginner |
| Recently Joined Staff Members | Sorting by date to find latest records | Beginner |
Over 500 learners have already sharpened their SQL skills on SQiLs. Start practicing now and join them.
Summary
ORDER BY and LIMIT are two of the most frequently used SQL clauses — and for good reason. Together they let you:
- Sort results in ascending or descending order by any column (or multiple columns)
- Restrict output to a manageable number of rows
- Paginate through large result sets with
OFFSET - Build Top-N and Bottom-N queries for dashboards and reports
The key takeaway: never assume your database will return rows in a predictable order. If order matters, spell it out with ORDER BY.
Ready to put these skills into practice? Try the sorting exercises on SQiLs — they use real databases and give you instant feedback on your queries.
FAQs
Can I use ORDER BY with GROUP BY?
Yes. ORDER BY runs after GROUP BY and HAVING, so you can sort aggregated results. For example, GROUP BY Country then ORDER BY COUNT(*) DESC gives you countries ranked by row count. See our GROUP BY and HAVING guide for more details.
What is the difference between LIMIT and TOP?
They do the same thing — restrict the number of rows returned. LIMIT is used in MySQL, PostgreSQL, and SQLite. TOP is SQL Server syntax (SELECT TOP 10 ...). Oracle uses FETCH FIRST n ROWS ONLY. The logic is identical across all databases.
Is OFFSET the only way to paginate?
No. OFFSET-based pagination is simple but can be slow for large offsets. Keyset pagination (also called cursor-based pagination) uses a WHERE clause on the last value from the previous page, which is much faster because it leverages indexes. Use OFFSET for small datasets and keyset pagination for production applications at scale.
Does ORDER BY slow down my query?
It can. Sorting requires the database to arrange all qualifying rows before returning results. If you sort by an indexed column, the database can often skip the sort entirely. For unindexed columns or complex expressions, sorting large result sets will add overhead. Combining ORDER BY with LIMIT helps because the database can use a partial sort (top-N heap) instead of sorting everything.



