Разработка и Конфигурация · 12 мин
ВЫБРАТЬ ПЕРВЫЕ в 1С: как работает отбор первых записей запроса
Как работает конструкция ВЫБРАТЬ ПЕРВЫЕ в запросах 1С: синтаксис, сортировка, соединения, типичные ошибки и способы проверить результат.
Конструкция ВЫБРАТЬ ПЕРВЫЕ N в языке запросов 1С ограничивает количество строк, которые вернёт запрос. Она используется, когда нужны не все данные, а только часть: последние документы, самый дорогой товар, первые несколько записей регистра. Механизм прост в записи, но содержит важный нюанс — без правильной сортировки понятие «первые» теряет смысл, и результат становится непредсказуемым.
Запрос с отбором первых записей встречается в типовых отчётах, обработках загрузки данных, проверках дублей и механизмах проверки заполнения. Разработчику важно понимать, в какой момент платформа применяет ограничение, как оно взаимодействует с сортировкой, соединениями и итогами, и почему один и тот же запрос может вернуть разные строки на разных СУБД.
Синтаксис и базовый принцип работы
Ключевое слово ПЕРВЫЕ указывается сразу после ВЫБРАТЬ и числа: ВЫБРАТЬ ПЕРВЫЕ 10. Далее следует обычный список полей, источник данных и условия. Платформа передаёт ограничение на уровень СУБД (для MS SQL это TOP, для PostgreSQL — LIMIT), поэтому выборка выполняется быстро и не тянет лишние данные на сервер 1С.
Пример простейшего запроса — десять последних по дате документов реализации:
ВЫБРАТЬ ПЕРВЫЕ 10
РеализацияТоваровУслуг.Ссылка КАК Документ,
РеализацияТоваровУслуг.Дата КАК Дата
ИЗ
Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
УПОРЯДОЧИТЬ ПО
Дата УБЫВ
Ограничение применяется к итоговому набору строк после отбора по условиям ГДЕ, группировки и сортировки. То есть сначала формируется полный логический результат, затем из него берутся первые N строк в порядке, заданном сортировкой.
Число записей можно передать параметром: ВЫБРАТЬ ПЕРВЫЕ &Количество. Это удобно в универсальных обработках, где объём выборки задаёт пользователь. Параметр должен быть целым положительным числом.
Почему без сортировки «первые» — это случайные записи
Главная ошибка при использовании конструкции — отсутствие УПОРЯДОЧИТЬ ПО. Логически таблица не имеет внутреннего порядка: СУБД вольна вернуть строки в любом порядке, который ей удобен по плану выполнения. На файловой базе запрос может стабильно возвращать одни и те же строки, а после переноса на клиент-серверный вариант результат изменится.
Зависимость от плана выполнения означает, что порядок может поменяться даже без смены платформы: после обновления статистики, реиндексации или роста объёма таблицы. Код, который «вчера работал», начнёт выбирать другие документы — такие дефекты трудно поймать при тестировании.
Правило простое: если в запросе есть ПЕРВЫЕ, в нём должна быть сортировка, которая однозначно определяет, какие строки считаются первыми. При равенстве значений поля сортировки (например, несколько документов с одинаковой датой) добавьте второй ключ — ссылку или номер документа, чтобы порядок был детерминирован.
Сортировка и однозначность результата
Поля даты в документах 1С имеют точность до секунды, поэтому документы, введённые в одну секунду, формально равны по дате. В демонстрационной базе это редкость, в реальной — обычная ситуация при обменах и пакетном проведении. Добавьте в сортировку уникальное поле:
УПОРЯДОЧИТЬ ПО
Дата УБЫВ,
Документ УБЫВ
Сортировка по ссылке не даёт хронологического порядка (GUID не упорядочен по времени создания), но обеспечивает стабильность: при одинаковых датах одна и та же пара документов всегда попадёт в выборку в одном порядке. Для хронологии внутри секунды используйте момент времени документа через точку маршрута МоментВремени или сортировку по дате с добавлением номера.
ПЕРВЫЕ в сочетании с соединениями и группировками
Когда запрос содержит соединения, ограничение применяется к результату после соединения. Если нужно взять первые строки из одной таблицы и только потом присоединить к ним данные, вынесите отбор во вложенный запрос или временную таблицу. Иначе дублирование строк при соединении «один ко многим» сократит фактическое число уникальных объектов: ПЕРВЫЕ 10 по строкам соединения может дать лишь три разных документа.
Пример: сначала отбираем пять последних заказов, затем подтягиваем их товары:
ВЫБРАТЬ ПЕРВЫЕ 5
Заказ.Ссылка КАК Заказ
ПОМЕСТИТЬ ПоследниеЗаказы
ИЗ
Документ.ЗаказКлиента КАК Заказ
УПОРЯДОЧИТЬ ПО
Заказ.Дата УБЫВ
;
ВЫБРАТЬ
Товары.Ссылка КАК Заказ,
Товары.Номенклатура КАК Номенклатура,
Товары.Количество КАК Количество
ИЗ
Документ.ЗаказКлиента.Товары КАК Товары
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПоследниеЗаказы КАК Отбор
ПО Товары.Ссылка = Отбор.Заказ
С группировкой ПЕРВЫЕ отбирает первые строки агрегированного результата. Классический сценарий — топ-5 товаров по сумме продаж: группировка по номенклатуре, суммирование, сортировка по сумме по убыванию и ПЕРВЫЕ 5. Здесь сортировка обязательна по тому же агрегату, по которому определяется «топ».
ПЕРВЫЕ и итоги
Секция ИТОГИ ПО строится по уже ограниченному набору строк. Если в выборку попали первые 10 детальных записей, итоги посчитаются только по ним, а не по всей таблице. Для отчётов, где нужен итог по всем данным и одновременно «топ», используйте два отдельных запроса или пакет с временными таблицами.
Практические сценарии использования
Наиболее частые задачи, где конструкция уместна: получение последнего значения периодического регистра сведений (хотя для этого правильнее использовать срез последних), проверка существования хотя бы одной записи, выборка порции данных для пакетной обработки, построение топ-списков в отчётах.
Для проверки «существует ли запись» запрос с ПЕРВЫЕ 1 предпочтительнее полной выборки: СУБД остановит поиск после первой найденной строки. После выполнения проверяйте РезультатЗапроса.Пустой() — это стандартный и быстрый паттерн.
Для пакетной обработки больших объёмов (например, перепроведение миллиона документов) ПЕРВЫЕ 1000 в цикле с запоминанием последней обработанной даты и ссылки позволяет обрабатывать данные порциями, не держать в памяти всю выборку и безопасно прерывать процедуру.
- 1Сформулируйте запрос с ВЫБРАТЬ ПЕРВЫЕ N и нужными полями.
- 2Добавьте УПОРЯДОЧИТЬ ПО по дате с направлением УБЫВ.
- 3Добавьте второй ключ сортировки (ссылку или номер) для однозначности.
- 4Выполните запрос и проверьте, что вернулось ожидаемое число строк.
- 5Проверьте запрос в консоли на копии базы с реальным объёмом данных.
Типичные ошибки и ограничения
Первая ошибка — ожидание, что ПЕРВЫЕ 1 вернёт «последний документ» без сортировки. Вторая — использование конструкции для задач, где платформа предлагает специализированные механизмы: срез первых и срез последних виртуальных таблиц периодических регистров сведений. Виртуальная таблица СрезПоследних решает задачу «актуальное значение на дату» корректнее и обычно быстрее, чем самодельный запрос с ПЕРВЫЕ 1 и сортировкой по периоду.
Третья группа ошибок связана с динамическими списками. В динамическом списке произвольный запрос с ПЕРВЫЕ ограничивает набор, но при этом теряется часть функциональности: корректная работа отбора по ссылочным полям, интерактивная сортировка пользователем. Для форм списков лучше использовать стандартные настройки динамического списка, а не жёсткое ограничение в тексте запроса.
Как проверить, что запрос работает правильно
Проверку удобно выполнять в консоли запросов на копии рабочей базы. Сначала выполните запрос без ПЕРВЫЕ, но с той же сортировкой, и посмотрите первые строки результата. Затем добавьте ограничение и сравните: набор строк должен совпадать с началом полной выборки.
Обратите внимание на граничные ситуации: пустую таблицу (запрос должен вернуть пустой результат без ошибки), количество записей меньше N (вернётся всё, что есть), записи с одинаковыми значениями ключа сортировки на границе отбора. Последний случай — источник «мигающих» результатов, и лечится он добавлением уникального ключа сортировки.
Как проверить результат
Строки идут строго по заданной сортировке, первые N совпадают с началом полной выборки
Порядок меняется между запусками одного и того же запроса
При равных значениях ключа сортировки набор стабилен благодаря второму ключу
На границе то попадает, то не попадает одна и та же запись
Запрос возвращает пустой результат, код корректно обрабатывает РезультатЗапроса.Пустой()
Ошибка при обращении к полям выборки без проверки на пустоту
Производительность и влияние на базу
Само по себе ограничение ускоряет запрос: СУБД прекращает сканирование, как только набрано нужное число строк. Но это верно только при наличии подходящего индекса под сортировку. Если сортировка идёт по неиндексированному полю или по выражению, СУБД сначала выберет и отсортирует весь набор, и только потом отсечёт лишнее — выигрыша по времени почти не будет.
Для тяжёлых отборов проверяйте план запроса средствами СУБД или через технологический журнал. Если запрос с ПЕРВЫЕ выполняется медленно, причина обычно в сортировке большого промежуточного результата: пересмотрите условия ГДЕ, чтобы сузить набор до сортировки, или добавьте индекс по полям отбора и упорядочивания.
Если запрос с ПЕРВЫЕ используется в цикле для пакетной обработки, не сортируйте по модифицируемому в цикле полю — иначе обработанные записи могут снова попасть в следующую порцию. Надёжнее запоминать последнюю пару «дата + ссылка» и отбирать записи строго позже неё.
Частые вопросы
Чем ВЫБРАТЬ ПЕРВЫЕ отличается от РАЗЛИЧНЫЕ?
Это независимые конструкции. РАЗЛИЧНЫЕ убирает дубли строк из результата, а ПЕРВЫЕ ограничивает их количество. Их можно комбинировать: ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ 10 — сначала устраняются дубли, затем берутся первые десять уникальных строк в порядке сортировки.
Можно ли передать число записей параметром?
Да. Записывается как ВЫБРАТЬ ПЕРВЫЕ &Количество, а в коде параметру присваивается целое число: Запрос.УстановитьПараметр("Количество", 100). Передавать ноль или отрицательное значение не следует — поведение зависит от СУБД и может привести к ошибке.
Как получить последнюю запись периодического регистра сведений?
Правильный способ — виртуальная таблица СрезПоследних с указанием периода и условий по измерениям. Запрос с ПЕРВЫЕ 1 и сортировкой по периоду по убыванию даст похожий результат, но требует аккуратной обработки границы периода (включать ли запись ровно на указанную дату) и обычно уступает срезу по производительности.
Почему запрос с ПЕРВЫЕ возвращает разные строки на файловой и серверной базе?
Если в запросе нет сортировки или сортировка неоднозначна, порядок строк определяет СУБД по своему плану выполнения. Файловая и клиент-серверная СУБД строят разные планы, поэтому «первые» строки различаются. Решение — явное УПОРЯДОЧИТЬ ПО с уникальным ключом.
Работает ли ПЕРВЫЕ во вложенных запросах и временных таблицах?
Да, конструкция допустима во вложенных запросах и при выборке во временные таблицы. Это стандартный приём: сначала во временную таблицу помещают ограниченный набор ключей, затем соединяют его с детальными данными. Во временной таблице порядок строк не сохраняется, поэтому сортировку для финального результата нужно задавать во внешнем запросе.
Что быстрее: ПЕРВЫЕ 1 или обход всей выборки с прерыванием?
ПЕРВЫЕ 1 быстрее и проще: ограничение выполняется на стороне СУБД, лишние строки не передаются на сервер 1С и в код. Выборка всего результата с выходом из цикла после первой итерации заставит СУБД подготовить полный набор, что на больших таблицах заметно дороже.
Что важно запомнить
ВЫБРАТЬ ПЕРВЫЕ N ограничивает число строк результата на уровне СУБД. Какие строки попадут в выборку, определяет только сортировка: без УПОРЯДОЧИТЬ ПО результат произволен. Для стабильности добавляйте уникальный ключ сортировки, для соединений выносите отбор во временную таблицу, а для периодических регистров сведений используйте срезы вместо самодельных запросов.