Топ контрибуторов
loading
loading
Знаете ли Вы, что

Вы можете подписаться на RSS ленту новых тестов сервиса Quizful, в том числе и отдельно по каждой категории

Лента обновлений
ссылка Oct 22 23:24
Комментарий от alexcei88:
В вопросе переменная s даже не выводиться, а выводитьс...
ссылка Oct 22 17:46
Комментарий от AlexFurm:
Это UB, так можно вызывать только статические функции ч...
ссылка Oct 22 17:43
Комментарий от AlexFurm:
Любые битовые операции с signed это UB
ссылка Oct 21 20:30
Комментарий от yoori:
Любой вариант скомпилируется если компилировать не в конеч...
ссылка Oct 21 16:53
Добавлен вопрос в тест QA (Quality Assurance)
Статистика

Тестов: 153, вопросов: 8596. Пройдено: 443368 / 2177510.

Разбиение на страницы в SQL (paging, постраничка)

head tail Статья
категория
Базы данных
дата15.07.2009
авторmanuna
голосов17

[Disclaimer: Данная статья была переведена в рамках "Конкурса на лучший перевод статьи" на сервисе Quizful. Ссылка на оригинал находится внизу страницы.]

Разбиение на страницы — это термин, обозначающий получение подвыборки даных из набора записей. Представьте, что имеется список из 1000 записей, но пользователю одновременно все они не нужны — тогда есть смысл разбить их на страницы. Устанавливается размер страницы и пользователь одновременно сможет просматривать, скажем, по 50 или по 100 записей на странице, перелистывая их по мере надобности.

Обычным практическим примером использования этого в сети является программное обеспечение форумов. Вместо отображения 9 миллиардов ответов темы, оно отображает только 10 за раз. Почему? Во-первых, если пользователь хочет увидеть новые сообщения в цепочке, ему надо будет загрузить только последнюю страницу (или только первую, если надо просмотреть лишь начало темы). Во-вторых, если сервер будет отдавать по 10 сообщений, то в 99 случаях из 100 это уменьшит требуемую пропускную способность канала и время загрузки страниц.

Давайте посмотрим на SQL для генерации набора записей:

SELECT * FROM table_name

Этот запрос вернет все даные из таблицы table_name. Если же мы хотим получить первые 30 записей этой таблицы, надо будет использовать синтаксис, специфический для базы данных (то есть один и тот же запрос не станет работать для MS SQL Server и для MySQL). Для MySQL запрос выглядит так:

SELECT *  FROM table_name LIMIT 30

А для MS SQL server - вот так:

SELECT TOP 30 * FROM table_name

LIMIT, как вы уже догадались — это удивительное ключевое слово. У него есть два варианта: один выбирает первые <сколько-там-указано> записей, а другой выбирает диапазон. Итак — что если нам нужна третья “страница” данных, записи с 61 по 90? С использованием LIMIT, в MySQL это будет выглядеть вот так:

SELECT * FROM table_name LIMIT 60, 30

Синтаксис LIMIT такой:

LIMIT <смещение>, <количество строк>

Итак, все просто — как два байта переслать. А вот в MS SQL — совсем другое дело. Как пользователь MySQL, MS SQL и PostgreSQL, могу со всей ответственностью заявить, что это почти что самая раздражающая дыра в MS SQL,которую следовало бы пофиксить еще пару лет назад... Но вернемся к коду:

SELECT *
FROM (
SELECT TOP 30 *
FROM (
SELECT TOP 90 *
FROM table_name
) AS internal
ORDER BY internal.ID DESC
) AS external
ORDER BY external.ID ASC

Я предупреждал, что это будет уродством. Давайте посмотрим, что же оно творит. Самый внутрений запрос выглядит так же, как и начальный, не считая того, что он вытаскивает все записи до конца нужной страницы.

Второй запрос реверсирует упорядочивание (так, чтобы порядок ID данных был 90, 89, 88, 87, ...) и берет первые 30 записей.

И самый внешний запрос разворачивает их в обратном порядке, чтобы они были отсортированы как и вначале.

У Oracle есть свой собственный способ работы со страницами (с использованием достаточно интуитивно понятной переменной ROWNUM, подставляемой в выражение WHERE). Это выглядит так:

SELECT * FROM table_name WHERE ROWNUM > 60 AND ROWNUM <= 90

PostgreSQL использует альтернативный способ (который был также введен в синтаксис MySQL):

SELECT * FROM table_name LIMIT 30 OFFSET 60

При создании системы, которая может использовать одни и те же SQL-запросы на разных базах данных, следует хорошенько подумать о том, как будет производиться разбиение на страницы. Возможно, в такой среде проще будет запросить у базы все ID и вручную определить, как располагаются диапазоны, а потом выбрать их при помощи WHERE.

Надеюсь, кому-то это пригодится.

----------
Оригинальный текст статьи: Paging In SQL

Если Вам понравилась статья, проголосуйте за нее

Голосов: 17  loading...
manuna   clumsy   googperson   googman   googler   admin   Crabar   globus   ulidtko   SunDrop   c0nst   access   denmir   helpa   fil7   sefire   WooDmaN