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