iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

ORDER BY / LIMIT

ORDER BY sorts; LIMIT caps the result set. Together they drive pagination, top-N queries, and “newest first” feeds — with painful tail behaviour if you don’t use indexes.

Top-N, paging, keyset pagination

EXAMPLE
-- 1) ORDER BY — multi-column, mixed direction
SELECT id, total, created_at
FROM orders
ORDER BY created_at DESC, total DESC
LIMIT 20;

-- 2) LIMIT N OFFSET M — classic pagination (degrades on large offsets)
SELECT id, title FROM posts
ORDER BY id DESC
LIMIT 20 OFFSET 1000;       -- page 51 — scans 1020 rows

-- 3) Keyset pagination — O(log N) regardless of page depth
-- Page 1
SELECT id, title FROM posts
ORDER BY id DESC
LIMIT 20;
-- Page 2 — using last id from page 1
SELECT id, title FROM posts
WHERE id < 12345
ORDER BY id DESC
LIMIT 20;

-- 4) Composite keyset (multi-column ORDER BY)
SELECT id, posted_at, title FROM posts
WHERE (posted_at, id) < ('2026-06-07 12:00', 87651)
ORDER BY posted_at DESC, id DESC
LIMIT 20;

-- 5) Top-N per group — ROW_NUMBER (MySQL 8+)
SELECT * FROM (
    SELECT o.*,
           ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY total DESC) rn
    FROM orders o
) t
WHERE rn <= 3;

-- 6) Latest-per-user — fast pattern
SELECT o.* FROM orders o
JOIN (
    SELECT user_id, max(created_at) AS latest
    FROM orders
    GROUP BY user_id
) m ON m.user_id = o.user_id AND m.latest = o.created_at;

-- 7) ORDER BY without an index = filesort
-- Verify with EXPLAIN — Using filesort means MySQL sorted in-memory or to disk.
EXPLAIN SELECT * FROM posts ORDER BY views DESC LIMIT 10;
-- Add an index that matches your ORDER BY
CREATE INDEX posts_views_desc ON posts(views DESC);

-- 8) Random sampling — beware ORDER BY RAND()
-- BAD: O(N) sort
SELECT * FROM big_table ORDER BY RAND() LIMIT 5;
-- BETTER: random offset over an indexed key range
SELECT * FROM big_table
WHERE id >= FLOOR(RAND() * (SELECT MAX(id) FROM big_table))
ORDER BY id
LIMIT 5;

-- 9) Stable sort — ties resolved by adding the PK
SELECT * FROM posts ORDER BY views DESC, id DESC;     -- deterministic

-- 10) UNION + ORDER BY — wrap correctly
(SELECT id FROM a) UNION (SELECT id FROM b)
ORDER BY id DESC
LIMIT 10;

Why it matters

Switch to keyset pagination as soon as offsets get big. LIMIT 20 OFFSET 100000 scans all 100,020 rows; WHERE id < ? seeks directly. Same UX, dramatically better tail latency.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
SELECT * FROM products
ORDER BY price DESC, name ASC
LIMIT 20 OFFSET 40;   -- page 3 of 20
Try it Yourself »

Discussion

Loading…