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