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

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

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

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

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

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

Ниже разобраны основные способы с примерами кода, типичные ошибки, ограничения каждого подхода и рекомендации по выбору. Все примеры применимы к типовому синтаксису встроенного языка 1С и языка запросов.

Способ 1. Функция КОЛИЧЕСТВО в тексте запроса

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

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

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

"ВЫБРАТЬ

| КОЛИЧЕСТВО(*) КАК КоличествоЗаписей

|ИЗ

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

|ГДЕ

| Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода";

Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДата()));

Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекущаяДата()));

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

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

КоличествоДокументов = Выборка.КоличествоЗаписей;

КонецЕсли;

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

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

Способ 2. Подсчёт через Выгрузить() и метод Количество()

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

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

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

ЧислоСтрок = ТаблицаДанных.Количество();

Сообщить("Получено записей: " + ЧислоСтрок);

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

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

Способ 3. Перебор выборки со счётчиком

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

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

Счетчик = 0;

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

Счетчик = Счетчик + 1;

// обработка текущей записи

КонецЦикла;

Сообщить("Обработано записей: " + Счетчик);

Отдельно стоит упомянуть проверку на пустоту результата. Если нужно просто узнать, есть ли хотя бы одна запись, не обязательно считать их все — достаточно метода Пустой() у результата запроса. Это быстрее и читабельнее, чем сравнение счётчика с нулём.

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

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

Сообщить("Записей не найдено");

КонецЕсли;

Сравнение способов

КОЛИЧЕСТВО в запросе

Самый быстрый для чистого подсчёта; вычисляется на СУБД, не переносит данные в память. Ограничение: возвращает только число, сами записи недоступны.

Выгрузить().Количество()

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

Перебор со счётчиком

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

Результат.Пустой()

Оптимален для проверки «есть ли хотя бы одна запись». Не даёт точного количества.

Подсчёт с группировкой: сколько записей в каждой категории

На практике часто нужно не общее число, а количество записей по группам: сколько документов у каждого контрагента, сколько строк в каждом заказе, сколько сотрудников в каждом подразделении. Для этого КОЛИЧЕСТВО комбинируется с предложением СГРУППИРОВАТЬ ПО.

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

"ВЫБРАТЬ

| Реализация.Контрагент КАК Контрагент,

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

|ИЗ

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

|СГРУППИРОВАТЬ ПО

| Реализация.Контрагент

|УПОРЯДОЧИТЬ ПО

| КоличествоДокументов УБЫВ";

Такой запрос вернёт по одной строке на каждого контрагента с числом его документов. Сортировка по убыванию сразу покажет самых «активных» контрагентов. Этот же приём используется для поиска дублей: группы, где количество больше единицы, указывают на повторяющиеся значения.

Для фильтрации групп по количеству применяется предложение ИМЕЮЩИЕ — аналог ГДЕ, но для агрегированных данных. Например, ИМЕЮЩИЕ КОЛИЧЕСТВО(*) > 1 оставит только группы с дублями.

Поиск дублей через ИМЕЮЩИЕ

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

"ВЫБРАТЬ

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

| КОЛИЧЕСТВО(*) КАК ЧислоЗаписей

|ИЗ

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

|СГРУППИРОВАТЬ ПО

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

|ИМЕЮЩИЕ

| КОЛИЧЕСТВО(*) > 1";

Порядок действий при поиске дублей
  1. 1
    Сформируйте запрос с группировкой по проверяемому полю и КОЛИЧЕСТВО(<em>)
  2. 2
    Добавьте условие ИМЕЮЩИЕ КОЛИЧЕСТВО(</em>) > 1
  3. 3
    Выполните запрос и выгрузите результат
  4. 4
    Проверьте список значений вручную перед любым массовым изменением данных

Подсчёт записей в консоли запросов и СКД

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

В системе компоновки данных (СКД) количество записей выводится как ресурс с агрегатной функцией Количество(). Достаточно добавить в настройки отчёта вычисляемое поле или ресурс вида Количество(Ссылка) — и отчёт покажет число записей по каждой группировке и в общем итоге. Это стандартный способ построения отчётов «количество чего-либо по чему-либо» без программирования.

В динамических списках форм количество отображаемых записей можно оценить через основной реквизит списка, но точный подсчёт с учётом отборов проще выполнить отдельным запросом с теми же условиями, что и у списка.

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

Производительность и ограничения

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

Выгрузка результата в таблицу значений — самый «тяжёлый» вариант по памяти. Таблица значений хранится целиком, и при выборках в сотни тысяч строк это может привести к заметному росту потребления памяти на сервере 1С. Если нужно только число — никогда не выгружайте данные ради подсчёта.

Отдельное ограничение касается итогов по иерархии: при обходе выборки с типом обхода «По группировкам с иерархией» счётчик в цикле будет учитывать и строки групп, и строки детальных записей. Чтобы посчитать только детальные записи, проверяйте тип записи выборки или используйте обход «По группировкам» с переходом к детальным записям внутри групп.

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

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

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

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

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

Проверка результата и контрольные точки

После получения числа полезно убедиться, что оно соответствует ожиданиям. Самый простой способ — выполнить тот же запрос в консоли запросов и сравнить количество строк результата с вычисленным значением. Расхождение обычно указывает на различия в параметрах отбора или на ошибку в логике подсчёта.

Если считаются записи с группировкой, сверьте сумму по группам с общим количеством без группировки — они должны совпадать. Это быстрый способ поймать ошибки в условиях соединений и фильтрах.

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

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

Сравнение с консолью запросов
Норма

Число из кода совпадает с числом строк в консоли при тех же параметрах

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

Значения расходятся — проверьте параметры и условия отбора

Сумма по группам
Норма

Сумма КОЛИЧЕСТВО по всем группам равна общему КОЛИЧЕСТВО(<em>) без группировки

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

Сумма меньше общего числа — часть записей теряется из-за соединения или NULL в поле группировки

Проверка на NULL
Норма

КОЛИЧЕСТВО(</em>) и КОЛИЧЕСТВО(Поле) дают одинаковый результат

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

КОЛИЧЕСТВО(Поле) меньше — в поле есть значения NULL

Маршрут решения

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

Нужно только число записей, сами данные не требуютсяИспользуйте КОЛИЧЕСТВО(<em>) в тексте запроса
Результат запроса уже выгружен в таблицу значенийВызовите метод Количество() у таблицы
Записи обходятся в цикле для обработкиДобавьте счётчик в существующий цикл, отдельный запрос не нужен
Нужно узнать только, есть ли хотя бы одна записьИспользуйте Результат.Пустой() — это быстрее подсчёта
Нужно количество по категориям или поиск дублейПримените КОЛИЧЕСТВО(</em>) с СГРУППИРОВАТЬ ПО и при необходимости ИМЕЮЩИЕ

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

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

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

Как посчитать количество уникальных значений в запросе?

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

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

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

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

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

Как посчитать записи, удовлетворяющие условию, уже после выполнения запроса?

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

Итог

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

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