LIMIT и FETCH в SQL

Занимательный факт: В SQL-стандарте не предусмотрен limit.

Все используют limit:

select * from employees
order by salary desc
limit 5;
┌────┬──────────┬────────────┬────────┐
│ id │   name   │ department │ salary │
├────┼──────────┼────────────┼────────┤
│ 25 │ Иван     │ it         │ 120    │
│ 23 │ Леонид   │ it         │ 104    │
│ 24 │ Марина   │ it         │ 104    │
│ 33 │ Анна     │ sales      │ 100    │
│ 31 │ Вероника │ sales      │ 96     │
└────┴──────────┴────────────┴────────┘

А согласно стандарту, следует использовать fetch:

select * from employees
order by salary desc
fetch first 5 rows only;

fetch first N rows only делает то же, что и limit N. Но вообще fetch может больше.

Лимит с одинаковыми значениями

Допустим, мы хотим выбрать топ-5 сотрудников по зарплате, и заодно всех, у кого такая же зарплата, как у последнего из этой пятерки. Используем для этого with ties:

select * from employees
order by salary desc
fetch first 5 rows with ties;
┌────┬──────────┬────────────┬────────┐
│ id │   name   │ department │ salary │
├────┼──────────┼────────────┼────────┤
│ 25 │ Иван     │ it         │ 120    │
│ 23 │ Леонид   │ it         │ 104    │
│ 24 │ Марина   │ it         │ 104    │
│ 33 │ Анна     │ sales      │ 100    │
│ 31 │ Вероника │ sales      │ 96     │
│ 32 │ Григорий │ sales      │ 96     │
└────┴──────────┴────────────┴────────┘

Относительный лимит

Допустим, мы хотим выбрать верхние 10% сотрудников по зарплате. Поможет percent:

select * from employees
order by salary desc
fetch first 10 percent rows only;
┌────┬──────────┬────────────┬────────┐
│ id │   name   │ department │ salary │
├────┼──────────┼────────────┼────────┤
│ 25 │ Иван     │ it         │ 120    │
│ 23 │ Леонид   │ it         │ 104    │
└────┴──────────┴────────────┴────────┘

(всего 20 сотрудников, так что 10% — это 2 записи)

Лимит со смещением

Допустим, мы хотим пропустить 3 первых сотрудников и выбрать 5 следующих. Без проблем: fetch сочетается с offset точно так же, как limit:

select * from employees
order by salary desc
offset 3 rows
fetch next 5 rows only;
┌────┬──────────┬────────────┬────────┐
│ id │   name   │ department │ salary │
├────┼──────────┼────────────┼────────┤
│ 33 │ Анна     │ sales      │ 100    │
│ 31 │ Вероника │ sales      │ 96     │
│ 32 │ Григорий │ sales      │ 96     │
│ 22 │ Ксения   │ it         │ 90     │
│ 21 │ Елена    │ it         │ 84     │
└────┴──────────┴────────────┴────────┘

next здесь — просто синтаксический сахар, синоним для first, который использовался в предыдущих примерах. Можно заменить next на first с точно таким же результатом:

select * from employees
order by salary desc
offset 3 rows
fetch first 5 rows only;

Кстати, row и rows тоже синонимы.

Совместимость

fetch поддерживают эти СУБД:

  • PostgreSQL 8.4+
  • Oracle 12c+
  • MS SQL 2012+
  • DB2 9+

Но только Oracle поддерживает относительные лимиты (percent).

А MySQL и SQLite не поддерживают fetch вовсе.

──

P.S. Хотите освоить современный SQL? Обратите внимание на Оконные функции

Подписывайтесь на твитер, чтобы не пропустить новые заметки 🚀