Why interviewers love this: ORDER BY looks tiny, but it tests whether you know the difference between a result set and a predictable result set.
Question: What does ORDER BY do in SQL?
Answer: ORDER BY sorts query results by one or more columns or expressions. By default it sorts in ascending order, and you can switch to descending with DESC. Without ORDER BY, SQL does not guarantee row order, even if a small test seems to come back the same way.
Interview-Ready Answer: I use ORDER BY when I need rows in a predictable sequence. It can sort by one field or several fields, like salary DESC, name ASC, and I usually add a tie-breaker such as an id. One important detail is that if I do not specify ORDER BY, the database is free to return rows in any order, so I never rely on the natural order of a table.
ORDER BY is the final sorting step of a query. It does not create rows or remove rows; it only decides the sequence of the rows you already selected.
WHERE to remove non-matches.GROUP BY or aggregates, it builds grouped rows next.SELECT list is computed, including aliases and expressions like salary * 12.ORDER BY keys, such as created_at DESC or department, salary DESC.LIMIT or FETCH FIRST, the order decides which rows make the cut.| Clause | Main job | Changes row count? | Typical use |
|---|---|---|---|
| ORDER BY | Sort rows | No | Display, paging |
| WHERE | Filter rows | Yes | Find matches |
| GROUP BY | Combine rows | Yes | Aggregates |
Use it when the user cares about recency, priority, ranking, alphabetical lists, or stable pagination. If you are showing page 1 of products, you need a sort key that never changes unexpectedly. In practice, a common pattern is ORDER BY created_at DESC, id DESC so the newest row appears first and ties are still deterministic.
A plain sort is usually O(n log n) time because the engine must compare rows repeatedly. Memory depends on row width: 1 million rows at about 200 bytes each is roughly 200 MB before overhead, so wide sorts can become expensive fast. Many engines use an external sort when memory is not enough, which means they write temporary files to disk; that is much slower than an in-memory sort. If the query only needs the top 10 or top 100 rows, some optimizers can use a top-N strategy with a priority queue, which behaves closer to O(n log k), where k is the number of rows you keep.
ORDER BY, row order is not guaranteed.A, a, and accented letters may sort differently by database or locale.NULLS FIRST/LAST where available, or use COALESCE to control the position yourself.ORDER BY can sort by an alias or expression, but ordinal positions like ORDER BY 1 are fragile because column order changes break them.Real-world story: In an e-commerce checkout service, the admin page showing recent orders must list the newest orders first. The query was written as SELECT id, customer_id, created_at FROM orders WHERE store_id = ? LIMIT 20 with no ORDER BY, so different database nodes returned rows in different physical storage order.
That caused page 1 to show older orders above newer ones, and pagination became unstable: an order could appear on page 1 during one request and page 2 on the next. Support agents saw confusing behavior, logs showed the same SQL text, and users reported that urgent refunded orders were not visible at the top.
The fix was simple but important: sort by created_at DESC, id DESC. The secondary id tie-breaker made the order deterministic when multiple orders shared the same timestamp.
-- Re-runnable demo: a small employee table with ties and a NULL value.
DROP TABLE IF EXISTS employees;
CREATE TABLE employees (
id INTEGER PRIMARY KEY,
name VARCHAR(50) NOT NULL,
department VARCHAR(50) NOT NULL,
salary INTEGER
);
INSERT INTO employees (id, name, department, salary) VALUES
(1, 'Asha', 'Engineering', 120000),
(2, 'Ben', 'Engineering', 120000),
(3, 'Cara', 'Sales', 90000),
(4, 'Diego', 'Sales', 110000),
(5, 'Eli', 'Support', NULL);
-- Sort by salary descending; name breaks ties so equal salaries are predictable.
SELECT id, name, department, salary
FROM employees
ORDER BY salary DESC, name ASC;
-- Edge case: NULL salaries. COALESCE turns NULL into a small number so missing values sort last.
SELECT id, name, department, salary
FROM employees
ORDER BY COALESCE(salary, -1) DESC, name ASC;
-- ORDER BY can use a computed alias from the SELECT list.
SELECT name, salary, COALESCE(salary, 0) * 12 AS annual_salary
FROM employees
ORDER BY annual_salary DESC, name ASC;Follow-up & Tricky Questions:
ORDER BY use aliases? Yes. Because it runs after SELECT, you can sort by a computed alias like annual_salary. That keeps repeated expressions out of the sort clause and makes queries easier to read.ORDER BY sort by a column that is not in the SELECT list? Usually yes, as long as the query shape allows it. The database sorts by the underlying data, not just by what you display.ASC and DESC? ASC means low to high and is the default; DESC means high to low. If you sort by dates, DESC is common for newest first.ORDER BY created_at DESC, id DESC avoids duplicates or missing rows across pages.ORDER BY affect performance? It can force the database to sort many rows before returning anything, which may be expensive. If an index matches the sort order, the engine may avoid a full sort and read rows in order instead.ORDER BY 1 a good shortcut? It works in many databases because it means first selected column, but it is brittle. If someone reorders the select list later, the sort silently changes.ORDER BY happen before WHERE? Logically, no. WHERE filters first, then the remaining rows are sorted, so you should think of sorting as a late step in the query.Common Mistakes:
ORDER BY when the order matters, even if the test data looks stable.ORDER BY 1 in important queries. Fix: spell out column names or aliases so refactors do not silently change the sort.Memory Hook: Think of a nightclub: WHERE is the bouncer who decides who gets in, and ORDER BY is the usher who lines everyone up inside. Filtering comes first, sorting comes after.
Cheat Sheet:
ORDER BY sorts the final rows.ASC.ORDER BY means no guaranteed order.Practice Tasks:
customers table by last_purchase_date DESC and then id ASC.NULL scores last using COALESCE.