В разработке на платформе 1С часто возникает задача обработки данных, хранящихся в ТаблицеЗначений. Одна из самых распространенных операций — это агрегация данных, то есть группировка таблицы по одному или нескольким полям с одновременным подсчетом итогов (суммы, количества и т.д.) по другим полям. Например, у нас есть список продаж, где каждая строка — это товар и сумма, и нам нужно получить итоговую сумму по каждому уникальному товару.
Рассмотрим два основных, наиболее эффективных способа решения этой задачи: простой и быстрый метод Свернуть() и более мощный и гибкий подход с использованием объекта Запрос. Проанализируем каждый из них, чтобы вы могли выбрать наиболее подходящий для вашей ситуации.
Метод Свернуть() объекта ТаблицаЗначений является самым простым и прямолинейным способом для выполнения группировки с суммированием. Он идеально подходит для несложных случаев, когда требуется только сложить числовые значения.
Важный момент: метод Свернуть() модифицирует исходную таблицу значений, в которой он вызывается. После выполнения метода в таблице останутся только сгруппированные строки с итоговыми суммами.
Синтаксис метода выглядит следующим образом:
МояТаблица.Свернуть("КолонкиГруппировки", "КолонкиСуммирования");
Где:
Предположим, у нас есть таблица продаж, которую нужно сгруппировать по номенклатуре и подсчитать общую сумму продаж для каждого товара.
Для наглядности создадим таблицу программно и заполним ее данными. В реальной задаче эта таблица может быть получена из запроса или другого источника.
// Создаем новую таблицу значений
ТЗ_Продажи = Новый ТаблицаЗначений;
// Добавляем колонки
ТЗ_Продажи.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
ТЗ_Продажи.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
ТЗ_Продажи.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
// Заполняем данными
НоваяСтрока = ТЗ_Продажи.Добавить();
НоваяСтрока.Номенклатура = "Стол офисный";
НоваяСтрока.Сумма = 5000;
НоваяСтрока.Количество = 1;
НоваяСтрока = ТЗ_Продажи.Добавить();
НоваяСтрока.Номенклатура = "Стул офисный";
НоваяСтрока.Сумма = 2500;
НоваяСтрока.Количество = 2;
НоваяСтрока = ТЗ_Продажи.Добавить();
НоваяСтрока.Номенклатура = "Стол офисный";
НоваяСтрока.Сумма = 10000;
НоваяСтрока.Количество = 2;
НоваяСтрока = ТЗ_Продажи.Добавить();
НоваяСтрока.Номенклатура = "Тумба подкатная";
НоваяСтрока.Сумма = 3000;
НоваяСтрока.Количество = 1;
// До этого момента таблица содержит 4 строки
Свернуть().
Теперь вызовем метод, указав, что группировать нужно по колонке "Номенклатура", а суммировать — по колонкам "Сумма" и "Количество".
ТЗ_Продажи.Свернуть("Номенклатура", "Сумма, Количество");
// Теперь таблица ТЗ_Продажи изменена и содержит 3 сгруппированные строки
После выполнения этого кода в таблице ТЗ_Продажи останется всего три строки:
Преимущества метода Свернуть():
Недостатки:
Когда возможностей метода Свернуть() недостаточно, на помощь приходит язык запросов 1С. Этот способ является более универсальным, производительным на больших объемах данных и позволяет выполнять любые агрегатные функции.
Основная идея — передать нашу таблицу значений в запрос в качестве временной таблицы (источника данных) и уже средствами языка запросов выполнить группировку и расчет итогов. Также в новых версиях платформы доступно добавление данных в существующую временную таблицу.
Ключевое преимущество: запрос не изменяет исходную таблицу. Он возвращает результат в виде новой таблицы, что позволяет сохранить первоначальные данные без изменений.
Возьмем ту же самую исходную таблицу ТЗ_Продажи, которую мы создали в предыдущем примере.
Запрос.
Сначала создаем сам объект, затем передаем в него нашу таблицу как параметр. Имя параметра ("ИсходнаяТаблица" в нашем примере) мы будем использовать в тексте запроса для обращения к ней.
// 1. Создаем объект Запрос
Запрос = Новый Запрос;
// 2. Устанавливаем нашу таблицу в качестве параметра
// Имя "ИсходнаяТаблица" - произвольное, мы будем использовать его в тексте запроса
Запрос.УстановитьПараметр("ИсходнаяТаблица", ТЗ_Продажи);
В тексте запроса мы указываем, какие поля выбрать, какие агрегатные функции применить и по каким полям сгруппировать результат.
// 3. Пишем текст запроса
Запрос.Текст =
"ВЫБРАТЬ
| ИсходнаяТаблица.Номенклатура КАК Номенклатура,
| СУММА(ИсходнаяТаблица.Сумма) КАК ИтоговаяСумма,
| СУММА(ИсходнаяТаблица.Количество) КАК ИтоговоеКоличество,
| КОЛИЧЕСТВО(*) КАК КоличествоСтрок
|ИЗ
| &ИсходнаяТаблица КАК ИсходнаяТаблица
|
|СГРУППИРОВАТЬ ПО
| ИсходнаяТаблица.Номенклатура";
Проанализируем текст запроса:
ВЫБРАТЬ ...: перечисляем поля, которые войдут в результат.СУММА(...): агрегатная функция для суммирования.КОЛИЧЕСТВО(*): агрегатная функция для подсчета количества строк в группе.КАК ...: псевдоним для результирующей колонки, чтобы дать ей осмысленное имя.ИЗ &ИсходнаяТаблица: указываем источник данных. Амперсанд & означает, что это параметр, который мы установили ранее.СГРУППИРОВАТЬ ПО ...: указываем поле для группировки.После выполнения запроса результат выгружается в новую, результирующую таблицу значений или выводится в дерево значений.
// 4. Выполняем запрос и выгружаем результат в новую таблицу
РезультатГруппировки = Запрос.Выполнить().Выгрузить();
// Теперь переменная РезультатГруппировки содержит сгруппированную таблицу,
// а ТЗ_Продажи осталась без изменений.
Запрос не только посчитал суммы, но и смог вычислить количество исходных строк для каждой номенклатуры, что невозможно сделать с помощью метода Свернуть(). Вы можете использовать и другие агрегатные функции: МАКСИМУМ(), МИНИМУМ(), СРЕДНЕЕ().
Преимущества использования Запроса:
ГДЕ, например, при сравнении строк с представлением ссылки), соединять несколько таблиц.Недостатки:
Выбор между Свернуть() и Запросом зависит от конкретной задачи:
ТаблицаЗначений.Свернуть(), когда вам нужно быстро решить простую задачу: сгруппировать данные по одной или нескольким колонкам и только просуммировать значения в других. Это идеальный вариант для небольших, локальных операций, где читаемость и краткость кода важнее гибкости, и вас устраивает, что исходная таблица будет изменена.
Запрос во всех остальных случаях. Если вам нужна производительность на больших данных, если требуются агрегатные функции, отличные от суммирования (количество, среднее, максимум), если нужно сохранить исходные данные или если логика группировки сложна, запрос — это ваш основной и самый надежный инструмент. Освоение языка запросов является ключевым навыком для любого профессионального 1С-разработчика.