Sorting & Limiting Results
MySQL doesn't promise any particular row order unless you ask for one, and it will happily hand
back every matching row unless you tell it when to stop. ORDER BY controls the
first, and LIMIT controls the second - together they turn a raw result set into
exactly the slice of data a StreamHub page actually wants to display.
ORDER BY - Sorting Results
By default, ORDER BY sorts ascending (smallest or earliest first). Add
DESC to flip that around. Here's StreamHub's catalog sorted newest-first:
SELECT title, release_year
FROM movies
ORDER BY release_year DESC;
| title | release_year |
|---|---|
| Signal Lost | 2024 |
| The Last Reel | 2019 |
| Harbor Lights | 2016 |
Sorting by Multiple Columns
List several columns, in priority order, separated by commas. Ties in the first column are broken by the second. Here are StreamHub's reviews grouped by movie, then ranked best-to-worst within each movie:
SELECT movie_id, rating, review_date
FROM reviews
ORDER BY movie_id, rating DESC;
| movie_id | rating | review_date |
|---|---|---|
| 18 | 5 | 2026-05-12 |
| 18 | 3 | 2026-04-02 |
| 42 | 5 | 2026-07-30 |
| 42 | 4 | 2026-06-11 |
Notice each movie_id group stays together, and within every group the highest
rating comes first - that's DESC applying only to the second sort key, exactly as
written.
LIMIT - Capping the Number of Rows
Add LIMIT to cut a result set down to a fixed number of rows. StreamHub's 10 most recent reviews, site-wide:
SELECT movie_id, rating, review_date
FROM reviews
ORDER BY review_date DESC
LIMIT 10;
No matter how many thousands of reviews StreamHub has collected, this always returns exactly 10 rows - the most recent ones.
LIMIT with OFFSET - Pagination
Add OFFSET to skip a number of rows before starting to return results - the
standard way to fetch a specific "page" of data. Here's page 2 of StreamHub's movie list, 20
movies per page (so page 2 skips the first 20 and returns the next 20):
SELECT title, release_year
FROM movies
ORDER BY title
LIMIT 20 OFFSET 20;
MySQL also accepts a shorthand with no OFFSET keyword - the same query written that way:
SELECT title, release_year
FROM movies
ORDER BY title
LIMIT 20, 20;
LIMIT m, n, the first number is the offset and the second is the row count - the reverse order from writing LIMIT n OFFSET m out in full. Mixing the two forms up is an easy way to fetch the wrong page.
This is conceptually the exact same problem solved at the application layer in
flask-querying-filtering-pagination.php and django-pagination.php
elsewhere on this site - there, a framework builds this same LIMIT/OFFSET
query for you behind a page number. Here, it's happening directly in the database, which is
exactly what those frameworks are doing under the hood.
Combining ORDER BY and LIMIT - "Top N" Queries
Sorting and limiting together produce one of the most common query patterns in real applications: the "top N" query. StreamHub's 5 highest-rated movies, best first:
SELECT m.title, AVG(r.rating) AS avg_rating
FROM movies m
JOIN reviews r ON r.movie_id = m.id
GROUP BY m.id
ORDER BY avg_rating DESC
LIMIT 5;
| title | avg_rating |
|---|---|
| Signal Lost | 4.80 |
| The Last Reel | 4.60 |
| Harbor Lights | 4.50 |
| Reel to Reel | 4.20 |
| Quiet Static | 4.10 |
Notice this query needed AVG() and GROUP BY just to compute "average
rating per movie" before ORDER BY and LIMIT could even act on it - we
cover both properly in Aggregate Functions and
GROUP BY & HAVING, coming up soon in this track.
ORDER BY on a large table with no supporting index means MySQL has to sort every matching row from scratch on every single query, which gets slow as a table grows. Indexes, later in this track, covers how an index can let MySQL read rows back in already-sorted order instead.WHERE clause - comparison operators, logical operators, and pattern matching.