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

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

Как получить количество строк в запросе 1С

Способы получить количество строк в запросе 1С: функция КОЛИЧЕСТВО, Выбрать().Количество(), Выгрузить(). Примеры кода, типичные ошибки и советы.

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

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

Ниже разобраны все рабочие варианты с примерами кода, критериями выбора, ограничениями и типичными ошибками, которые допускают разработчики при работе с результатами запросов.

Подсчёт строк функцией КОЛИЧЕСТВО в тексте запроса

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

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

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

"ВЫБРАТЬ

| КОЛИЧЕСТВО(*) КАК КоличествоСтрок

|ИЗ

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

|ГДЕ

| НЕ Номенклатура.ПометкаУдаления";

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

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

Если Выборка.Следующий() Тогда

КоличествоСтрок = Выборка.КоличествоСтрок;

КонецЕсли;

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

Условие в секции ГДЕ применяется до подсчёта, поэтому вы получите количество именно тех строк, которые удовлетворяют отбору. Это правильный способ ответить на вопрос «сколько записей соответствует условию», не загружая сами записи.

Метод Количество() у выборки из результата запроса

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

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

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

"ВЫБРАТЬ

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

| Товары.Количество КАК Количество

|ИЗ

| Документ.РеализацияТоваровУслуг.Товары КАК Товары

|ГДЕ

| Товары.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);

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

ЧислоСтрок = Выборка.Количество();

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

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

Подсчёт через выгрузку в таблицу значений или дерево

Метод Выгрузить() превращает результат запроса в таблицу значений, после чего количество строк определяется через Таблица.Количество(). Этот вариант оправдан, когда данные нужны многократно: для заполнения табличной части, передачи в форму, построения отчёта или повторных обходов.

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

ТаблицаРезультата = Результат.Выгрузить();

ЧислоСтрок = ТаблицаРезультата.Количество();

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

При выгрузке с обходом по группировкам (ОбходРезультатаЗапроса.ПоГруппировкам) результатом будет дерево значений. В этом случае Количество() у корневой коллекции строк вернёт число строк верхнего уровня, а для подсчёта всех строк потребуется рекурсивный обход — это частая причина неверных подсчётов.

Проверка наличия строк без подсчёта: Пустой()

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

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

Если Результат.Пустой() Тогда

Возврат; // данных нет, обрабатывать нечего

КонецЕсли;

Этот приём быстрее и логичнее, чем сравнение Выборка.Количество() = 0, и существенно эффективнее выгрузки. Ещё один вариант — вызвать Выборка.Следующий() один раз: если метод вернул Ложь, строк нет.

Для максимальной экономии ресурсов при проверке существования записей комбинируйте Пустой() с конструкцией ВЫБРАТЬ ПЕРВЫЕ 1: запрос вернёт не более одной строки, и СУБД не будет сканировать всю таблицу до конца, если запись найдена раньше.

Порядок действий для проверки наличия данных
  1. 1
    Сформируйте запрос с ВЫБРАТЬ ПЕРВЫЕ 1 и нужным отбором
  2. 2
    Выполните запрос и сохраните результат в переменную
  3. 3
    Проверьте Результат.Пустой()
  4. 4
    Если результат не пустой — выполните основной запрос и обработайте данные

Сравнение способов и критерии выбора

Выбор метода зависит от того, что вы собираетесь делать с данными дальше. Ошибочный выбор — основная причина проблем с производительностью в прикладном коде.

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

Как выбрать способ

Нужно только число записей по условиюИспользуйте КОЛИЧЕСТВО(*) в тексте запроса
Данные нужны для обхода в циклеВыполните запрос и вызовите Выборка.Количество()
Данные нужны многократно или в формеВыгрузите в таблицу значений и возьмите её Количество()
Важен только факт наличия записейИспользуйте ВЫБРАТЬ ПЕРВЫЕ 1 и Результат.Пустой()

Типичные ошибки при подсчёте строк

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

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

Третья ошибка — подсчёт строк в запросе с соединениями. Левое соединение с таблицей, где одной записи соответствует несколько строк, размножает результат, и КОЛИЧЕСТВО(*) покажет больше, чем реальных документов. В таких случаях применяйте КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Ссылка) или пересматривайте структуру запроса.

Типичные ошибки
01
Чтение поля выборки без вызова Следующий() — обращение к несуществующей позиции
02
Выгрузка большого результата в таблицу значений только ради подсчёта — перерасход памяти
03
Подсчёт КОЛИЧЕСТВО(Поле) вместо КОЛИЧЕСТВО(*) — строки с NULL не учитываются
04
Игнорирование размножения строк при соединениях — завышенное число записей
05
Ожидание общего числа строк у выборки по группировкам — метод возвращает строки текущего уровня

Проверка результата и отладка запроса

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

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

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

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

Число из КОЛИЧЕСТВО(*) против числа строк запроса без агрегации
Норма

Значения совпадают

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

Количество завышено — проверьте соединения на размножение строк

Результат при реальных параметрах отбора
Норма

Возвращается ожидаемое число записей

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

Ноль при заведомо существующих данных — проверьте параметры и условия

Поведение на больших таблицах
Норма

Запрос выполняется быстро, память не растёт

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

Долгое выполнение — добавьте индексируемые условия отбора

Часто задаваемые вопросы

Чем отличается КОЛИЧЕСТВО(*) от КОЛИЧЕСТВО(1)?

Практически ничем: обе формы считают все строки результата. Форма КОЛИЧЕСТВО(1) иногда используется как привычка из других СУБД. Главное — не путать их с КОЛИЧЕСТВО(Поле), которая пропускает строки со значением NULL в указанном поле.

Как посчитать строки в каждой группе, а не общее число?

Добавьте группировку: перечислите поле группировки в секции ВЫБРАТЬ вместе с КОЛИЧЕСТВО(*) и укажите его в секции СГРУППИРОВАТЬ ПО. Запрос вернёт по одной строке на каждое значение группы с количеством записей в ней.

Почему Выборка.Количество() возвращает меньше строк, чем есть в таблице?

Если выборка получена с обходом по группировкам, метод возвращает число строк текущего уровня, а не всего результата. Либо в запросе применены отбор, соединение с дубликатами или конструкция РАЗЛИЧНЫЕ, сокращающие итоговый набор.

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

Да, если результат уже получен: используйте Количество() у выборки или у выгруженной таблицы значений. Повторный запрос нужен только если вы хотите получить число через КОЛИЧЕСТВО(*) отдельно от основной выборки данных.

Что быстрее: КОЛИЧЕСТВО() или выгрузка с подсчётом?

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

Как узнать количество записей в табличной части документа?

Если документ загружен в объект, используйте ДокументОбъект.Товары.Количество() — запрос не нужен. Если работаете со ссылкой без чтения объекта, выполните запрос к табличной части с КОЛИЧЕСТВО(*) и отбором по ссылке.

Итог

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

Для точного числа строк без данных используйте КОЛИЧЕСТВО(*) в тексте запроса, для уже полученной выборки — метод Количество(), для проверки наличия записей — Результат.Пустой() с ВЫБРАТЬ ПЕРВЫЕ 1. Не выгружайте большие результаты в таблицу значений ради одного числа и учитывайте влияние NULL и соединений на результат подсчёта.