Работа с данными в 1С:Предприятие часто требует точного подсчёта записей — будь то проверка объёма справочников перед выгрузкой, анализ остатков в регистрах или оптимизация запросов. Однако стандартный интерфейс платформы не всегда показывает количество строк в таблице наглядно, а в некоторых случаях (например, при работе с большими массивами данных) ручной подсчёт просто невозможен. Эта статья соберёт все актуальные способы определения количества строк — от базовых методов для начинающих до профессиональных техник с использованием языка запросов и встроенных функций.
Важно понимать, что выбор метода зависит от контекста: для таблицы значений в памяти подойдёт один подход, для регистра сведений в базе данных — другой, а при работе с динамическими списками в управляемых формах потребуются особые приёмы. Мы разберём каждый сценарий с примерами кода, предупреждениями о типичных ошибках и советами по оптимизации. Если вы когда-либо сталкивались с ситуацией, когда Таблица.Количество() возвращает неожиданный результат или запрос выполняется слишком долго — здесь вы найдёте объяснения и решения.
1. Базовый метод: функция Количество() для таблиц значений
Самый простой способ узнать количество строк — использовать встроенную функцию Количество() для объекта ТаблицаЗначений. Этот метод работает мгновенно, так как оперирует данными, уже загруженными в память. Пример:
Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Наименование");
Таблица.Колонки.Добавить("Количество");
Таблица.Добавить();
Таблица.Добавить();
Таблица.Добавить();
Сообщить(Таблица.Количество()); // Вернёт 3
Однако здесь есть нюансы:
- 🔹 Функция
Количество()возвращает физическое количество строк, включая пустые (если они были добавлены явно). - 🔹 Для динамических списков в управляемых формах этот метод не подходит — он вернёт количество строк, отображаемых на текущей странице, а не общее число записей.
- 🔹 Если таблица связана с источником данных (например, запросом), функция может вернуть 0 до момента фактической загрузки данных.
Чтобы избежать ошибок, всегда проверяйте, инициализирована ли таблица перед вызовом Количество(). Используйте конструкцию Если Таблица <> Неопределено Тогда.
2. Подсчёт строк в запросе: ВЫБРАТЬ КОЛИЧЕСТВО()
Когда данные хранятся в базе (справочники, документы, регистры), самый эффективный способ — использовать язык запросов 1С. Конструкция ВЫБРАТЬ КОЛИЧЕСТВО(*) вернёт точное число записей, соответствующих условиям отбора. Пример для справочника Номенклатура:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(*) КАК Количество
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| НЕ Номенклатура.ПометкаУдаления";
Результат = Запрос.Выполнить();
КоличествоСтрок = Результат.Выбрать().Количество; // 1250 (пример)
Преимущества метода:
- 🚀 Работает напрямую с базой данных, не загружая все строки в память.
- 🎯 Поддерживает сложные условия отбора (по датам, реквизитам, связям с другими таблицами).
- 📊 Можно комбинировать с группировкой:
ВЫБРАТЬ КОЛИЧЕСТВО(*) КАК КолВо, Номенклатура.ВидыНоменклатуры КАК Вид....
⚠️ Внимание: При работе с большими таблицами (миллионы записей) запрос КОЛИЧЕСТВО(*) может выполняться долго. В таких случаях используйте виртуальные таблицы или оптимизируйте индексы.
Использовать индексируемые поля в условиях ГДЕ|
Ограничить период дат, если это возможно|
Избегать SELECT * — указывать только нужные колонки|
Проверить права доступа к данным-->
3. Работа с динамическими списками в управляемых формах
Динамические списки — это элементы интерфейса, которые подгружают данные порциями (постранично). Здесь Количество() вернёт только число строк на текущей странице. Чтобы получить общее количество записей, используйте свойство ВсегоСтрок:
// В модуле формы
Процедура КнопкаПосчитатьНажатие(Кнопка)
Сообщить(ЭлементыФормы.СписокНоменклатуры.ВсегоСтрок);
КонецПроцедуры
Особенности метода:
- 📱 Работает только для управляемых форм (не подходит для обычных форм 8.2).
- 🔄 Если список имеет отбор,
ВсегоСтрокучтёт только видимые записи. - ⚡ Для больших списков (более 10 000 строк) может возникать задержка при первом обращении.
Если нужно посчитать строки с учётом пользовательских отборов, используйте комбинацию:
Отбор = ЭлементыФормы.СписокНоменклатуры.Отбор;
Запрос = Новый Запрос("ВЫБРАТЬ КОЛИЧЕСТВО(*) ИЗ Справочник.Номенклатура КАК Номенклатура");
Запрос.Текст = Запрос.Текст + Отбор.ПолучитьТекстЗапроса();
Количество = Запрос.Выполнить().Выбрать().Количество;
4. Альтернативные методы: Цикл и Счетчик
В некоторых случаях (например, при работе с массивами или коллекциями) удобно использовать ручной подсчёт через цикл. Этот метод универсален, но менее эффективен для больших объёмов данных:
Таблица = ПолучаемТаблицуЗначений(); // Предполагаем, что данные уже загружены
Счетчик = 0;
Для Каждого Строка Из Таблица Цикл
Счетчик = Счетчик + 1;
КонецЦикла;
Сообщить(Счетчик);
Когда это актуально:
- 🔧 Нужно не только посчитать строки, но и обработать каждую запись (например, проверить значения).
- 🧩 Работа с нестандартными структурами (вложенные таблицы, массивы массивов).
- 📝 Требуется логирование или дополнительные действия для каждой строки.
⚠️ Внимание: Для таблиц с более чем 10 000 строк цикл может значительно замедлить выполнение. В таких случаях лучше использовать ВЫБРАТЬ КОЛИЧЕСТВО() в запросе.
5. Продвинутые техники: Виртуальные таблицы и временные таблицы
Для оптимизации работы с большими объёмами данных в 1С:Предприятие 8.3 используются виртуальные таблицы и временные таблицы. Они позволяют уменьшить нагрузку на сервер и ускорить подсчёт.
Пример с виртуальной таблицей остатков:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(RAZNOST) КАК КоличествоУникальныхЗаписей
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаОтчета, ) КАК Остатки
|ГДЕ
| Остатки.Количество > 0";
Запрос.УстановитьПараметр("ДатаОтчета", ТекущаяДата());
Результат = Запрос.Выполнить();
Сравнение методов:
| Метод | Скорость | Память | Применимость |
|---|---|---|---|
Количество() |
⚡ Мгновенно | 🟢 Низкая | Таблицы значений в памяти |
ВЫБРАТЬ КОЛИЧЕСТВО(*) |
🟡 Зависит от индексов | 🟢 Низкая | Любые таблицы БД |
ВсегоСтрок |
🟡 Медленно для больших списков | 🟢 Низкая | Динамические списки |
| Цикл + Счетчик | 🐢 Медленно | 🔴 Высокая | Обработка каждой строки |
| Виртуальные таблицы | ⚡ Быстро | 🟢 Низкая | Регистры, большие данные |
Почему виртуальные таблицы быстрее?
Виртуальные таблицы не материализуют данные полностью — они работают с агрегированными результатами (например, остатками на дату), что сокращает объём обрабатываемой информации. Платформа 1С:Предприятие оптимизирует такие запросы на уровне СУБД, используя индексы и кэширование.
6. Типичные ошибки и как их избежать
Даже опытные разработчики иногда сталкиваются с неожиданными результатами при подсчёте строк. Вот самые распространённые ошибки:
- 🚫 Игнорирование пометки удаления: Запрос
ВЫБРАТЬ КОЛИЧЕСТВО(*) ИЗ Справочник.Контрагентывернёт все записи, включая помеченные на удаление. Всегда добавляйте условиеГДЕ НЕ ПометкаУдаления. - 🚫 Путаница с динамическими списками: Метод
Количество()для элемента формы ТабличноеПоле вернёт количество видимых строк, а не всех данных источника. - 🚫 Неучёт прав доступа: Если у пользователя нет прав на просмотр части данных, запрос
КОЛИЧЕСТВО(*)может вернуть заниженное значение. Проверяйте роли! - 🚫 Забывают про транзакции: При подсчёте строк в транзакции результат может отличаться от фактического состояния базы (если транзакция ещё не зафиксирована).
Как отладить проблемный подсчёт:
- Проверьте, совпадает ли количество строк в консоли запросов и в вашем коде.
- Используйте
ПояснитьЗапрос(), чтобы увидеть план выполнения: - Убедитесь, что отборы в запросе и в динамическом списке идентичны.
- Для больших таблиц тестируйте запрос на тестовой базе с аналогичным объёмом данных.
Всегда проверяйте подсчёт строк на тестовых данных перед использованием в рабочей базе — особенно если запрос содержит сложные условия или соединения таблиц.
7. Оптимизация производительности при подсчёте
Если подсчёт строк занимает слишком много времени, воспользуйтесь этими советами:
- 🛠️ Индексируйте поля, используемые в условиях
ГДЕ: Например, для запроса по датам добавьте индекс на реквизитДатаДокумента. - 🗃️ Разбивайте большие запросы: Вместо одного запроса на миллион записей используйте пакетную обработку (например, по месяцам).
- 🔄 Кэшируйте результаты: Если количество строк нужно часто, сохраняйте его в регистре сведений и обновляйте по расписанию.
- 📊 Используйте материализованные представления: В PostgreSQL или MS SQL можно создать представление с предварительно посчитанными агрегатами.
Пример оптимизированного запроса:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(*) КАК КолВо
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Реализация
|ГДЕ
| Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
| И Реализация.Организация = &Организация";
Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("Организация", Справочники.Организации.НашаФирма);
Результат = Запрос.Выполнить();
⚠️ Внимание: В кластерных базах (например, с использованием 1С:ГИС или распределённых информационных баз) подсчёт строк может давать разные результаты на разных узлах. В таких случаях используйте центральный сервер отчётности.
FAQ: Частые вопросы о подсчёте строк в 1С
Можно ли узнать количество строк в таблице без запроса к базе?
Да, но только если данные уже загружены в память. Для ТаблицыЗначений используйте Таблица.Количество(), для Массива — Массив.Количество(). Однако для данных, хранящихся в базе (справочники, документы, регистры), без запроса не обойтись.
Почему запрос КОЛИЧЕСТВО(*) выполняется долго?
Это типичная проблема для больших таблиц (более 1 млн записей). Причины:
- Отсутствуют индексы на поля, используемые в условиях
ГДЕ. - Запрос сканирует всю таблицу (например, если нет ограничения по дате).
- СУБД (MS SQL, PostgreSQL) не оптимизирует запрос из-за сложной структуры.
Решение: добавьте индексы, ограничьте период данных или используйте виртуальные таблицы.
Как посчитать строки в табличной части документа?
Для табличной части документа (например, Товары в РеализацииТоваровУслуг) используйте:
КоличествоСтрок = ДокументОбъект.Товары.Количество();
Если нужно посчитать строки с ненулевым количеством:
Счетчик = 0;
Для Каждого Строка Из ДокументОбъект.Товары Цикл
Если Строка.Количество > 0 Тогда
Счетчик = Счетчик + 1;
КонецЕсли;
КонецЦикла;
В чём разница между КОЛИЧЕСТВО(*) и КОЛИЧЕСТВО(Поле)?
КОЛИЧЕСТВО(*) подсчитывает все строки, соответствующие условиям, включая те, где поля содержат NULL. КОЛИЧЕСТВО(Поле) считает только строки, где указанное поле не равно NULL.
Пример:
// Вернёт количество НЕпустых значений в колонке "Телефон"
ВЫБРАТЬ КОЛИЧЕСТВО(Контрагент.Телефон) ИЗ Справочник.Контрагенты
Можно ли посчитать строки в отчёте (СКД)?
Да, в Системе Компоновки Данных (СКД) количество строк доступно через:
- Свойство
Результат.Вывод.КоличествоСтрокпосле выполнения отчёта. - Или через запрос к временной таблице результата (если нужно посчитать строки с определёнными условиями).
Пример:
Отчет = Отчеты.Продажи.Создать();
Отчет.Компоновать();
КоличествоСтрок = Отчет.Результат.Вывод.КоличествоСтрок;