К статье
Практический материал

Разработка и Конфигурация · 11 мин

Выборка в 1С: что это такое и как с ней работать

Выборка в 1С — это механизм перебора данных из результата запроса. Разбираем методы Выбрать, Следующий, обход по группировкам, типичные ошибки и примеры кода.

Выборка в 1С — это объект встроенного языка, который позволяет последовательно перебрать строки результата запроса или данные таблицы базы данных. Когда разработчик выполняет запрос методом Выполнить(), он получает результат запроса — своеобразный «снимок» данных. Чтобы прочитать из него строки одну за другой, результат преобразуют в выборку методом Выбрать(), а затем обходят её в цикле.

Термин «выборка» используется в 1С в двух близких смыслах. Во-первых, это объект ВыборкаИзРезультатаЗапроса — основной инструмент обхода данных запроса. Во-вторых, похожие выборки возвращают методы Выбрать() у менеджеров справочников, документов и других объектов — они позволяют перебрать элементы прямо из базы без написания запроса. В обоих случаях логика одинакова: выборка — это курсор, который движется по записям в одном направлении.

Понимание механизма выборки критично для любого разработчика 1С: почти каждая обработка, отчёт или проведение документа сводится к тому, чтобы получить набор строк и что-то с ними сделать. Ошибки при работе с выборкой приводят к пропущенным данным, лишним обращениям к базе и медленному коду.

Как устроена выборка из результата запроса

После выполнения запроса результат хранится в оперативной памяти. Метод Выбрать() создаёт выборку — указатель, который изначально стоит «перед первой строкой». Каждый вызов метода Следующий() сдвигает указатель на одну строку и возвращает Истина, если строка существует, или Ложь, когда строки закончились. Именно поэтому стандартный шаблон обхода выглядит так:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Товар,

| Номенклатура.Код КАК Код

|ИЗ

| Справочник.Номенклатура КАК Номенклатура";

Результат = Запрос.Выполнить();

Выборка = Результат.Выбрать();

Пока Выборка.Следующий() Цикл

Сообщить(Выборка.Код + " — " + Выборка.Товар);

КонецЦикла;

Обращение к полям текущей строки выполняется через точку: Выборка.Товар, Выборка.Код. Имена должны совпадать с псевдонимами полей в тексте запроса. Если поле не попало в выборку, обращение к нему вызовет ошибку исполнения.

Важная особенность: выборка однонаправленная. Если вы прошли её до конца, повторный обход той же выборки ничего не даст — нужно заново вызвать Результат.Выбрать() и получить новый объект. Это частая причина «пустого» второго цикла у начинающих разработчиков.

Выборка против выгрузки в таблицу значений

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

Выборка или таблица значений

Выборка (Выбрать)

Подходит для однократного последовательного обхода, особенно больших результатов. Экономит память, но не позволяет вернуться назад и искать произвольную строку.

Таблица значений (Выгрузить)

Подходит, когда данные нужны многократно: поиск по строкам, сортировка, свёртка, передача в другие процедуры. Требует больше памяти на больших объёмах.

Обход по группировкам

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

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

Обход по группировкам и итогам

Когда в запросе используется секция ИТОГИ, результат становится иерархическим: есть строки-итоги по группам и детальные строки внутри них. Метод Выбрать() принимает параметр типа обхода, который определяет, какие строки попадут в выборку.

  • ОбходРезультатаЗапроса.Прямой — все строки подряд, значение по умолчанию;
  • ОбходРезультатаЗапроса.ПоГруппировкам — только строки итогов по группировкам;
  • ОбходРезультатаЗапроса.ПоГруппировкамСИерархией — итоги с учётом иерархии.

Типовой приём — вложенные выборки: внешний цикл идёт по группам, а для каждой группы метод Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам) у самой выборки возвращает детальные записи. Так строят отчёты вида «контрагент → его документы» без дополнительных запросов в цикле.

ВыборкаПоКонтрагентам = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

Пока ВыборкаПоКонтрагентам.Следующий() Цикл

Сообщить("Контрагент: " + ВыборкаПоКонтрагентам.Контрагент);

Детали = ВыборкаПоКонтрагентам.Выбрать();

Пока Детали.Следующий() Цикл

Сообщить(" Документ: " + Детали.Документ);

КонецЦикла;

КонецЦикла;

Выборки через методы объектов: справочники и документы

Второй сценарий — выборки, которые возвращают менеджеры объектов без явного запроса. Например, Справочники.Номенклатура.Выбрать() вернёт выборку элементов справочника, а Документы.РеализацияТоваровУслуг.Выбрать(НачалоДня(Дата), КонецДня(Дата)) — документы за период. У этих выборок тоже есть метод Следующий(), а текущий объект доступен через свойство Ссылка.

Такие выборки удобны для простых задач: найти элементы по владельцу или родителю, перебрать документы за дату. Однако они ограничены: нельзя задать произвольное условие, соединить несколько таблиц или выбрать только нужные поля. Как только логика отбора усложняется, правильнее перейти на запрос — он выполнит фильтрацию на стороне СУБД и вернёт ровно те данные, которые нужны.

Типичные ошибки при работе с выборкой

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

Типичные ошибки
01
Повторный обход той же выборки: после первого цикла курсор в конце, второй цикл не выполнится. Решение — получить новую выборку через Результат.Выбрать() или выгрузить в таблицу значений.
02
Обращение к полю, которого нет в запросе: вызывает ошибку исполнения. Проверяйте, что псевдоним поля в тексте запроса совпадает с обращением в коде.
03
Запрос внутри цикла обхода: на каждую строку выполняется обращение к базе, производительность падает в десятки раз. Заменяйте соединением или временной таблицей.
04
Изменение данных объекта при обходе выборки по той же таблице без контроля транзакции: возможны блокировки и конфликты. Для массовых изменений используйте транзакции и пакетную обработку.
05
Игнорирование проверки Результат.Пустой(): код обхода не выполнится, но логика дальше может рассчитывать на данные. Добавляйте явную проверку и сообщение пользователю.

Отдельно стоит упомянуть путаницу между выборкой и ссылкой. Строка выборки — это не объект базы данных: изменить Выборка.Товар нельзя, это только чтение. Чтобы изменить элемент, нужно получить объект через Выборка.Ссылка.ПолучитьОбъект(), изменить и записать — и делать это осознанно, понимая, что каждая запись идёт в базу.

Как проверить корректность работы с выборкой

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

Контрольные точки

Как проверить результат

Количество обработанных строк
Норма

Счётчик в цикле совпадает с ожидаемым числом записей (можно сверить с консолью запросов)

Тревожный признак

Строк меньше, чем в данных, — проверьте отборы и соединения в запросе

Повторный обход
Норма

Перед вторым циклом выборка получена заново или результат выгружен в таблицу значений

Тревожный признак

Второй цикл молча не выполняется — выборка уже исчерпана

Производительность
Норма

Обход тысяч строк занимает секунды, обращений к базе внутри цикла нет

Тревожный признак

Время растёт линейно от числа строк из-за запросов или ПолучитьОбъект() в цикле

Поля выборки
Норма

Все обращения вида Выборка.Имя совпадают с псевдонимами полей запроса

Тревожный признак

Ошибка «Поле не найдено» при исполнении

Порядок действий при написании обхода
  1. 1
    Сформируйте и отладьте текст запроса в консоли запросов, убедитесь, что возвращаются нужные строки и поля.
  2. 2
    Выполните запрос методом Выполнить() и проверьте Результат.Пустой().
  3. 3
    Получите выборку методом Выбрать() с нужным типом обхода (прямой или по группировкам).
  4. 4
    Организуйте цикл Пока Выборка.Следующий() Цикл и обращайтесь к полям по псевдонимам.
  5. 5
    Проверьте счётчиком, что обработано ожидаемое число строк, и убедитесь, что внутри цикла нет лишних обращений к базе.

Когда выборка не нужна: альтернативы

Не каждая задача требует явного обхода. Если данные нужны только для показа пользователю, результат запроса можно напрямую вывести в табличный документ или использовать в схеме компоновки данных — СКД сама обойдёт набор и построит отчёт. Если нужно посчитать сумму или количество, это делается агрегатными функциями прямо в запросе (СУММА, КОЛИЧЕСТВО), без единой строки цикла.

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

Итог

Что важно запомнить

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

Частые вопросы о выборке в 1С

Чем выборка отличается от результата запроса?

Результат запроса — это весь набор данных, возвращённый СУБД. Выборка — объект для чтения этого набора по одной строке. Из одного результата можно получить несколько независимых выборок, вызывая Выбрать() повторно.

Можно ли узнать количество строк в выборке заранее?

У выборки есть метод Количество(), но для больших результатов надёжнее посчитать строки агрегатной функцией КОЛИЧЕСТО в отдельном запросе или использовать свойство результата. Учтите, что для выборок по группировкам Количество() возвращает число строк текущего уровня обхода.

Почему цикл по выборке не выполняется ни разу?

Чаще всего результат запроса пуст — проверьте Результат.Пустой() и отладьте текст запроса в консоли. Вторая причина — выборка уже была пройдена ранее: получите её заново через Результат.Выбрать().

Можно ли изменить данные прямо через выборку?

Нет, выборка доступна только для чтения. Чтобы изменить элемент, получите объект через Выборка.Ссылка.ПолучитьОбъект(), измените реквизиты и вызовите Записать(). Для массовых изменений оборачивайте операции в транзакцию и обрабатывайте данные порциями.

Что быстрее: выборка или таблица значений?

Для однократного последовательного обхода выборка обычно экономичнее по памяти, особенно на больших объёмах. Таблица значений выигрывает, когда к данным нужен многократный доступ, поиск и сортировка. Разница в скорости заметна только на крупных наборах данных.

Как обойти иерархический справочник с учётом вложенности?

Используйте в запросе секцию ИТОГИ ПО с ключевым словом ИЕРАРХИЯ или соединение с таблицей по иерархии, а затем обход с параметром ПоГруппировкамСИерархией. Для справочников также доступен метод ВыбратьИерархически() у менеджера справочника.