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