> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> Документация по сортировке, фильтрации и разбиению результата на страницы во встроенном Web SQL UI (`/play`)

# Сортировка, фильтрация и разбиение на страницы в Web UI

Встроенный Web SQL UI (`play.html`, доступный по пути [`/play`](/docs/ru/concepts/features/interfaces/http) на любом HTTP-порту ClickHouse) позволяет сортировать результат по столбцам, фильтровать его по их значениям и разбивать на страницы — и всё это без редактирования запроса.

Ни одна из этих операций не выполняется в браузере. При каждом изменении запрос выполняется повторно с соответствующей настройкой формирования запроса: сервер материализует её, оборачивая запрос в производную таблицу с внешними `ORDER BY`, `WHERE` и `LIMIT`. Таким образом, на экране отображается отсортированный, отфильтрованный и разбитый на страницы результат всего запроса, а не переставленные строки, которые случайно оказались на странице.

<div id="sorting">
  ## Сортировка
</div>

Справа от заголовка каждого столбца расположены две стрелки: ▲ сортирует результат по этому столбцу по возрастанию, ▼ — по убыванию. Щелчок по стрелке активирует соответствующую сортировку и повторно выполняет запрос; щелчок по уже активной стрелке отключает её, а щелчок по стрелке другого направления переключает сортировку в этом направлении. Стрелки — это настоящие кнопки, поэтому пользователи клавиатуры могут переходить к ним клавишей Tab и активировать их с клавиатуры; каждая стрелка также сообщает своё состояние вспомогательным технологиям (сам заголовок содержит `aria-sort`).

На устройствах с указателем, поддерживающим наведение (например, мышью), стрелки отображаются только при наведении на заголовок или когда стрелка находится в фокусе, чтобы в остальное время не мешать; на сенсорных и других устройствах с грубым указателем, где наведение недоступно, они отображаются всегда, чтобы их можно было нажать напрямую. Для столбца, по которому выполняется сортировка, обе стрелки отображаются без наведения: одна — чтобы направление сортировки было видно с первого взгляда, другая — потому что смена направления — наиболее вероятное следующее действие.

Каждый значок в заголовке столбца выглядит одинаково независимо от того, какой возможностью он управляет: он приглушён, пока эта возможность не задействована для столбца, и отображается цветом, зарезервированным для активных элементов управления — пурпурным в светлой теме, жёлтым в тёмной, — когда она задействована; в этом случае он также остаётся видимым без наведения. Приглушение означает отсутствие цвета, а не прозрачность, поэтому значок никогда не выглядит блеклым на фоне имени столбца или цветового кодирования ячеек.

<div id="sorting-by-several-columns">
  ### Сортировка по нескольким столбцам
</div>

При активации сортировки текущая сортировка заменяется: ранее отсортированные столбцы деактивируются, а выбранный столбец становится единственным ключом сортировки. Удерживайте <kbd>Shift</kbd> при щелчке, чтобы сохранить уже активные ключи сортировки и добавить этот столбец после них — именно в таком порядке они используются в `ORDER BY`: первый ключ определяет порядок, а каждый последующий разрешает совпадения по предыдущим. Если ключей сортировки несколько, каждая активная стрелка также показывает надстрочным индексом позицию своего столбца в этом порядке (▼¹, ▲², …).

Нажатие <kbd>Shift</kbd> на столбце, уже являющемся ключом сортировки, изменяет только направление сортировки и сохраняет его позицию в порядке. Деактивация столбца удаляет только этот столбец, оставляя остальные ключи на своих местах.

<div id="filtering">
  ## Фильтрация
</div>

<div id="filtering-from-a-column-header">
  ### Из заголовка столбца
</div>

В каждом заголовке столбца рядом со стрелками сортировки есть значок воронки, который появляется тем же способом. Нажатие на него открывает поле ввода предиката для этого столбца с кнопкой применения (▶) справа; заполнитель подсказывает формат предиката для типа столбца: `> 10` для числа, `LIKE '%test%'` для строки. Поле ввода открывается внутри ячейки заголовка, которая расширяется на вторую строку, чтобы освободить для него место. После установки фильтр отображается на той же строке, поэтому его редактируют там же, где читают. Вводится часть, следующая за именем столбца, поэтому `> 10` превращается в `WHERE column > 10`; можно использовать любое выражение, принимаемое сервером в этом месте: `BETWEEN 1 AND 5`, `IN (1, 2, 3)`, `IS NOT NULL`, `% 2 = 0`.

Нажатие кнопки применения (или <kbd>Enter</kbd>) применяет фильтр и повторно выполняет запрос; <kbd>Esc</kbd>, щелчок или переход по <kbd>Tab</kbd> в другое место отменяет редактирование и скрывает поле ввода. Кнопка применения неактивна, когда применять нечего: поле пусто и у столбца нет фильтра. Однако для пустого поля у столбца с фильтром она остаётся активной, поскольку очистка поля с последующим применением удаляет фильтр. Фильтры нескольких столбцов объединяются с помощью `AND`.

<div id="filtering-from-a-cell">
  ### Из ячейки
</div>

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

| Значение                                                    | Доступные варианты                                                                                     |
| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| Число                                                       | `=`, `!=`, `>`, `<`, `>=`, `<=`                                                                        |
| Дата или время (`Date`, `Date32`, `DateTime`, `DateTime64`) | `=`, `!=`, `>`, `<`, `>=`, `<=`                                                                        |
| Строка длиной не более 100 символов                         | `=`, `!=`, `contains` — для пустой строки доступны только `=` и `!=`, так как любая строка её содержит |
| `Bool`                                                      | `true`, `false` — сами значения, а не сравнение со значением этой ячейки                               |
| `Enum`                                                      | `=`, `!=` — частичное совпадение в закрытом наборе имён не является полезным фильтром                  |
| `NULL`                                                      | `IS NULL`, `IS NOT NULL`                                                                               |

Выбранный вариант применяется сразу. Дата, время или enum сравниваются с текстом в том виде, в котором его отобразил сервер; ClickHouse разбирает его обратно как тип самого столбца (для enum — как имя значения). `contains` преобразуется в шаблон `LIKE`, в котором символы `%` и `_` из значения экранируются, поэтому оно сопоставляется буквально. Для ячеек со значениями других типов — массивом, кортежем, map или длинным текстом — меню не отображается; при этом их столбцы по-прежнему можно фильтровать через поле ввода в заголовке.

<div id="the-filter-in-effect">
  ### Действующий фильтр
</div>

Под именем отфильтрованного столбца отображается предикат, пока фильтр активен, поэтому всегда видно, что строки на экране — это подмножество результата; значок воронки перемещается вниз, в левый нижний угол заголовка. При нажатии на предикат на его месте снова открывается поле ввода; кнопка ✕ рядом с ним удаляет фильтр, как и применение пустого поля ввода. В обоих случаях запрос выполняется повторно.

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

Если отфильтрованный результат оказывается пустым, заголовки столбцов сохраняются (вместо вертикального формата, в котором обычно отображается пустой результат), поэтому можно увидеть и снять фильтр, которому ничего не соответствует.

<div id="pagination">
  ## Пагинация
</div>

Отображается не более 1000 строк результата; для очень широких результатов это число может быть меньше. Если результат был обрезан из-за этого ограничения, под таблицей появляется пейджер:

```text theme={null}
Page: 1 2 …   Per page: 1000
```

При щелчке по номеру страницы размер страницы устанавливается равным лимиту отображения, а выбранный номер сохраняется в настройке [`page`](/docs/ru/reference/settings/session-settings/other#page), после чего запрос выполняется повторно; сервер преобразует номер страницы в соответствующий `OFFSET`. Пейджер остаётся, пока результат разбит на страницы, даже если каждая страница заполнена полностью и больше не выглядит обрезанной.

Количество страниц не отображается, поскольку оно неизвестно: для подсчёта строк результата потребовалось бы выполнить второй запрос. Пейджер показывает десять страниц перед текущей, текущую и следующую страницы, а затем `…`. При щелчке по `…` оно превращается в поле для ввода любого номера страницы; номер применяется, когда поле теряет фокус (это также происходит при нажатии <kbd>Enter</kbd>).

Следующая страница доступна только пока текущая заполнена полностью. Если возвращено меньше строк, чем помещается на странице, это означает конец результата, поэтому следующей страницы нет. (Если длина результата точно кратна размеру страницы, всё равно предлагается ещё одна страница, которая окажется пустой: чтобы отличить этот случай, снова пришлось бы подсчитывать строки.)

`На странице` показывает, сколько строк помещается на странице, и изменяется так же: щёлкните значение и введите другое. Оно не может превышать число строк, которое результат может отобразить одновременно: при большем размере страницы будут возвращены строки, которые таблица затем обрежет, а следующая страница начнётся после них. В результате при включённой разбивке на страницы строки, которые не поместились, будут молча пропущены. Большее число принимается как этот максимум и отображается в качестве значения. При его изменении снова открывается первая страница, поскольку страницы нового размера содержат другие строки.

Изменение сортировки или любого фильтра возвращает к первой странице: оба действия изменяют состав строк в результате или их порядок, поэтому страница, на которой находился пользователь, больше не соответствует тому же срезу результата.

<div id="how-it-is-applied">
  ## Как это применяется
</div>

Форма передаётся в качестве настроек формирования запроса: [`order`](/docs/ru/reference/settings/session-settings/other#order), [`filter`](/docs/ru/reference/settings/session-settings/other#filter), [`limit`](/docs/ru/reference/settings/session-settings/other#limit) и [`page`](/docs/ru/reference/settings/session-settings/other#page). Поскольку сервер применяет их к разобранному запросу, а не к его тексту, они сочетаются с любым содержимым уже существующего запроса: `UNION`, завершающее предложение `FORMAT`, а также собственные `ORDER BY` и `LIMIT` продолжают работать, при этом запрос в редакторе никогда не переписывается.

Имена столбцов передаются как идентификаторы в кавычках, поэтому столбец результата, имя которого представляет собой выражение (`count()`) или содержит пробел, можно использовать в качестве ключа сортировки или фильтра.

<div id="when-it-is-available">
  ## Когда это доступно
</div>

Настройка формы доступна только для операторов, к которым применимы эти настройки, то есть для запросов `SELECT` и `UNION` (в том числе запросов, начинающихся с предложения `WITH` или `FROM`). Она недоступна для `SHOW`, `DESCRIBE`, `EXISTS` и `EXPLAIN`: хотя они возвращают таблицу, настройки к ним не применяются, поэтому элемент управления в этом случае подразумевал бы результат, которого у строк нет.

Форма применяется к результату одного оператора, поэтому она недоступна при запуске нескольких операторов с помощью «Run all»: каждый из них представляет собой отдельный запрос с отдельными столбцами.

Она также недоступна для результата, содержащего не более одной строки на первой странице: любой порядок для одной строки одинаков, а фильтр может лишь оставить или исключить её, поэтому элементы управления могли бы только повторно выполнить запрос для тех же строк — а в пустом результате нет даже строки, которую можно исключить. По той же причине здесь скрыты переключатели [цветового кодирования](/docs/ru/concepts/features/interfaces/web-ui-color-coding): при наличии не более одной строки нечего сравнивать.

Для двух типов результатов с одной строкой элементы управления сохраняются, поскольку только они позволяют вернуться к исходному состоянию:

* результата, уже отсортированного или отфильтрованного: сортировка должна оставаться обратимой, а фильтр — очищаемым; фильтр, соответствующий одной строке, — это именно то, как длинный результат становится коротким, и удаление вместе с ним элементов управления оставило бы пользователя с включённым фильтром;
* результата, ограниченного лимитом отображения, который является первой страницей более длинного результата: размер страницы ограничен количеством ячеек, которые таблица может отобразить одновременно, поэтому очень широкий результат может быть сокращён до одной строки, а строки после неё — именно то, для доступа к чему предназначены сортировка и разбиение на страницы.

Форма привязана к оператору, для которого она была создана. При выполнении другого оператора — после редактирования запроса или перемещения курсора к другому оператору в редакторе с несколькими операторами — она сбрасывается, а не применяет `ORDER BY` или предложение WHERE к столбцу, которого может не быть в новом операторе.

Она также привязана к контексту, в котором был выполнен этот оператор: выбранной базе данных, серверу и пользователю, которому он был отправлен, а также значениям его параметров запроса. После изменения любого из этих параметров один и тот же текст может обозначать другие столбцы — например, `SELECT * FROM events` после переключения базы данных или `SELECT * FROM {tbl:Identifier}` после редактирования параметра. Поэтому форма также сбрасывается, а следующий запуск возвращает результат без настройки формы.

<div id="downloading-and-copying">
  ## Скачивание и копирование
</div>

При скачивании повторно выполняется исходный запрос с той же формой, поэтому экспортированный файл содержит те же строки в том же порядке, что и результат на экране. При копировании используется отображённый результат, поэтому он также полностью совпадает.

<div id="persistence">
  ## Сохранение
</div>

Форма запоминается в URL страницы (`sort_columns`, `filters`, `page` и `page_size`), истории браузера и снимке результата для каждой вкладки. Поэтому она сохраняется при перезагрузке страницы, переходе по ссылке, а также навигации назад и вперёд. Поскольку форма определяет не только представление, но и сами строки, общая ссылка, автоматически запускающая запрос (`run=1`), повторно выполняет его с той же формой и воспроизводит тот же результат. Сохраняется только активная форма: результат без неё ничего не добавляет в URL или состояние истории, чтобы они оставались компактными.

Как описано выше, восстановленный результат сохраняет форму, привязанную к контексту, в котором он был получен: снимок фиксирует базу данных, подключение и значения параметров, с которыми были получены его строки. Поэтому повторное выполнение оператора после изменения любого из этих параметров сбрасывает форму, а не применяет её к другому результату.

Как и [режимы цветового кодирования](/docs/ru/concepts/features/interfaces/web-ui-color-coding) и [закреплённые столбцы](/docs/ru/concepts/features/interfaces/web-ui-pinned-columns), форма хранится отдельно для каждой вкладки запроса, поэтому сортировка или фильтрация результата на одной вкладке не приводит к повторному выполнению результата на другой вкладке.

<div id="limitations">
  ## Ограничения
</div>

* Если сервер не может применить форму, запрос завершается ошибкой, которая отображается так же, как и для любого другого неудачного запроса. Затем форма удаляется, поскольку при неудачном выполнении не отображаются ни заголовки, ни пейджер, с помощью которых её можно было бы очистить.
* Сортировка и фильтрация идентифицируют столбец по его имени в результате. В результате одно и то же имя может встречаться дважды (`SELECT 1 AS x, 2 AS x`, JOIN таблиц с одинаковыми именами столбцов), и такие столбцы нельзя различить по имени, поэтому для них недоступны элементы управления сортировкой и фильтрацией; столбцы с уникальными именами в том же результате сохраняют эти элементы управления.
* Для сортировки по нескольким столбцам требуется клавиша <kbd>Shift</kbd>, поэтому она недоступна на устройствах с сенсорным экраном; сортировка по одному столбцу доступна.
* Вертикальное (транспонированное) представление результата из одной строки не содержит заголовков столбцов и, следовательно, элементов управления; по этой причине для результата, которому пользователь уже задал форму, сохраняется горизонтальное представление.
