Как выбрать первые 10 строк — LIMIT, TOP, FETCH FIRST
В SQLite, MySQL, MariaDB и PostgreSQL первые 10 строк даёт LIMIT:
SELECT id, name, price
FROM products
ORDER BY price DESC
LIMIT 10;LIMIT ставится в самом конце запроса, после ORDER BY. Без ORDER BY «первые» строки — какие попало: СУБД не обязана хранить и выдавать их в порядке добавления.
В разных СУБД
| СУБД | Первые 10 строк |
|---|---|
| SQLite, MySQL, MariaDB, PostgreSQL | SELECT … ORDER BY … LIMIT 10 |
| PostgreSQL, Oracle 12c и новее (стандарт SQL) | SELECT … ORDER BY … FETCH FIRST 10 ROWS ONLY |
| Microsoft SQL Server | SELECT TOP 10 … ORDER BY … |
| Oracle до 12c | WHERE ROWNUM <= 10 |
TOP пишется сразу после SELECT, а не в конце: SELECT TOP 10 id, name FROM products ORDER BY price DESC. SQLite не понимает ни TOP, ни FETCH FIRST — только LIMIT.
Последние 10 строк
Последние — это первые при обратной сортировке:
SELECT id, name FROM products ORDER BY id DESC LIMIT 10;Если нужно показать их в прямом порядке, оберните запрос в подзапрос и отсортируйте ещё раз:
SELECT * FROM (
SELECT id, name FROM products ORDER BY id DESC LIMIT 10
) AS last_rows
ORDER BY id;Страницы: OFFSET
OFFSET пропускает строки. Страница 3 по 10 строк — строки с 21-й по 30-ю:
SELECT id, name FROM products ORDER BY id LIMIT 10 OFFSET 20;Пропуск считается так: (номер страницы − 1) × размер страницы. В MySQL и SQLite есть и короткая запись LIMIT 20, 10 — сначала пропуск, потом число строк. Порядок легко перепутать, поэтому LIMIT … OFFSET … надёжнее.
На больших таблицах OFFSET 100000 медленный: СУБД всё равно читает и отбрасывает 100 000 строк. Для длинных списков листают «от последнего показанного»: WHERE id > 12345 ORDER BY id LIMIT 10.
Первые строки в каждой группе
Два самых дорогих товара в каждой категории — задача для оконной функции ROW_NUMBER() (SQLite 3.25 и новее, MySQL 8.0 и новее, PostgreSQL):
SELECT category, name, price
FROM (
SELECT category, name, price,
ROW_NUMBER() OVER (PARTITION BY category ORDER BY price DESC) AS n
FROM products
) AS ranked
WHERE n <= 2
ORDER BY category, price DESC;| category | name | price |
|---|---|---|
| Канцелярия | Пенал | 12 |
| Канцелярия | Тетрадь | 3 |
| Сумки | Рюкзак | 85 |
| Сумки | Сумка для ноутбука | 70 |
| Техника | Наушники | 60 |
| Техника | Калькулятор | 30 |
| Учёба | Глобус | 45 |
ROW_NUMBER() нумерует строки внутри каждой категории (PARTITION BY) по убыванию цены, а внешний запрос оставляет номера 1 и 2. Таблица — из учебной базы курса, см. урок Добавление строк.
Подводные камни
- Равные значения. Если у 10-й и 11-й строки одинаковая цена, какая из них попадёт в ответ, не определено. Добавьте в сортировку уникальный столбец:
ORDER BY price DESC, id. - LIMIT в подзапросе с IN. MySQL не поддерживает
LIMITвнутри подзапросаIN (SELECT … LIMIT 10)— оберните его в ещё один подзапрос вFROMили используйтеJOIN. - Число строк.
LIMITне говорит, сколько строк всего. Для подписи «страница 3 из 12» нужен отдельныйSELECT COUNT(*)— см. справку Как посчитать строки.