Как получить количество строк в выборке 1С до начала перебора элементов?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

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

Почему метод Количество() отсутствует в стандартной выборке менеджера?

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

Основная особенность объекта СправочникВыборка заключается в его динамической природе. Это так называемый «живой» курсор базы данных. Когда мы вызываем метод Выбрать(), система не считывает все данные из таблицы справочника в оперативную память сервера. Вместо этого она устанавливает указатель на начало данных. Порционная подгрузка (обычно по 25 элементов) происходит только в момент вызова метода Следующий().

Такой подход имеет свои преимущества и недостатки:

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

Поскольку система «не видит» всю выборку целиком, она не может вернуть значение количества. Чтобы решить эту проблему, нам необходимо изменить подход к получению данных.

Решение №1: Использование объекта Запрос и метода Количество() выборки

Если нам критически важно знать количество строк перед циклом, наиболее логичным решением будет использование объекта Запрос. В отличие от выборки менеджера, результат запроса позволяет получить метаданные о количестве строк.

Разберем по шагам, как это реализовать:

  1. Создаем объект Запрос и описываем текст на языке запросов 1С.
  2. Выполняем запрос и получаем РезультатЗапроса.
  3. Из результата получаем объект ВыборкаИзРезультатаЗапроса.

Посмотрим на пример кода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Номенклатура.Ссылка КАК Ссылка
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура";

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

// Теперь мы можем обратиться к количеству
КолВо = Выборка.Количество();

Если КолВо > 0 Тогда
    Сообщить("Количество элементов в выборке: " + КолВо);
    Пока Выборка.Следующий() Цикл
        // Обработка элементов
    КонецЦикла;
КонецЕсли;

В данном случае метод Количество() доступен, потому что РезультатЗапроса уже сформирован на стороне сервера базы данных, и платформа знает размер полученного набора данных.

Решение №2: Оптимизированный подсчет количества через функцию КОЛИЧЕСТВО(*)

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

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	КОЛИЧЕСТВО(*) КАК ОбщееКолВо
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура";

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

Если Выборка.Следующий() Тогда
    КоличествоСтрок = Выборка.ОбщееКолВо;
    Сообщить("Всего записей в справочнике: " + КоличествоСтрок);
КонецЕсли;

Этот способ работает значительно быстрее, так как SQL-серверу не нужно передавать клиенту список ссылок. Он просто возвращает результат вычислений. Для быстрого анализа объемов таблиц и генерации готовых запросов подсчета можно использовать обработку для подсчета количества документов с текстом запроса.

Решение №3: Проверка на наличие данных без точного подсчета

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

Для таких целей у объекта РезультатЗапроса существует метод Пустой(). Это самый быстрый способ проверки наличия данных. Рассмотрим правильный паттерн работы:


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

Если Не РезультатЗапроса.Пустой() Тогда
    Выборка = РезультатЗапроса.Выбрать();
    Пока Выборка.Следующий() Цикл
        // Работа с данными
    КонецЦикла;
КонецЕсли;

Метод Пустой() отрабатывает мгновенно, так как системе достаточно найти первое совпадение по условиям запроса, чтобы вернуть результат.

Особенности работы с регистрами сведений

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

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

Выгрузка в Таблицу значений (для небольших объемов)

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


РезультатЗапроса = Запрос.Выполнить();
ТаблицаДанных = РезультатЗапроса.Выгрузить();

// У таблицы всегда есть свойство Количество()
КолВо = ТаблицаДанных.Количество();

Важно: Не используйте этот метод для выборок, содержащих десятки и сотни тысяч строк, так как это может привести к критическому потреблению памяти сервером 1С.

Подведем итоги

Мы рассмотрели различные способы получения количества элементов в выборке. Подведем краткий итог:

Использование правильного метода в зависимости от контекста задачи позволит вашему коду работать не только правильно, но и максимально производительно.

← На главную