В практике разработки на платформе 1С:Предприятие 8 часто возникает ситуация: мы пишем сложный запрос, используем конструкцию СГРУППИРОВАТЬ ПО, но вместо ожидаемых двух-трех итоговых строк получаем множество записей, где данные разнесены по разным строкам. В этой статье мы подробно разберем, почему так происходит, и как заставить запрос «схлопнуть» данные в одну строку по конкретному аналитическому разрезу (например, по контрагенту).
Для начала проанализируем ситуацию: у нас есть набор данных, где информация распределена по периодам (например, 12 колонок для месяцев). Мы хотим видеть одну строку по контрагенту, где в каждой колонке будет стоять соответствующее значение. Если строки «не схлопываются», это означает только одно: в полях, указанных в блоке группировки, есть различия. Для СУБД значения "Иванов" и "Иванов " (с пробелом) или две даты, различающиеся на одну секунду, — это абсолютно разные записи.
Рассмотрим правильную структуру запроса, к которой необходимо прийти для агрегации данных:
|ВЫБРАТЬ
| ВТ_Пол.Контрагент КАК Контрагент,
| ВТ_Пол.Номенклатура КАК Номенклатура,
| СУММА(ВТ_Пол.Количество1) КАК Количество1,
| СУММА(ВТ_Пол.Сумма1) КАК Сумма1,
| СУММА(ВТ_Пол.Количество2) КАК Количество2,
| СУММА(ВТ_Пол.Сумма2) КАК Сумма2
|ИЗ
| ВТ_Данные КАК ВТ_Пол
|СГРУППИРОВАТЬ ПО
| ВТ_Пол.Контрагент,
| ВТ_Пол.Номенклатура
В этом примере поля Контрагент и Номенклатура являются измерениями, а суммы и количества — ресурсами. Все, что не обернуто в агрегатную функцию (СУММА, МАКСИМУМ, МИНИМУМ), обязано присутствовать в блоке СГРУППИРОВАТЬ ПО.
Выясним самую распространенную причину неудачных группировок. Если в блоке СГРУППИРОВАТЬ ПО указано поле Период, и данные в таблицу попали из документов или разных регистров, время в этих датах может отличаться. Визуально в отчете вы можете видеть 01.01.2023, но внутри системы одна запись может иметь время 10:00:00, а другая — 12:00:00.
Рассмотрим, как правильно нормализовать период, чтобы строки объединились в рамках месяца:
|ВЫБРАТЬ
| НАЧАЛОПЕРИОДА(ВТ_Пол.Период, МЕСЯЦ) КАК ПериодМесяц,
| ВТ_Пол.Контрагент КАК Контрагент,
| СУММА(ВТ_Пол.Сумма1) КАК Сумма1
|ИЗ
| ВТ_Пол КАК ВТ_Пол
|СГРУППИРОВАТЬ ПО
| НАЧАЛОПЕРИОДА(ВТ_Пол.Период, МЕСЯЦ),
| ВТ_Пол.Контрагент
Функция НАЧАЛОПЕРИОДА отсекает «лишнюю» точность времени и приводит все даты к единому стандарту (например, к 00:00:00 первого числа месяца). Если же период в итоговой таблице вообще не важен для вывода, его следует просто исключить из списка полей ВЫБРАТЬ и из блока СГРУППИРОВАТЬ ПО.
Проанализируем ситуацию, когда данные собираются из нескольких таблиц через ЛЕВОЕ СОЕДИНЕНИЕ. Если для какого-то контрагента во второй таблице нет данных, система вернет значение NULL. Группировка по полю, содержащему NULL, и полю со значением (даже если это пустая строка или ноль) создаст две разные строки.
Для ресурсов (числовых показателей) использование функции ЕСТЬNULL критически важно для корректного суммирования:
|ВЫБРАТЬ
| ВТ_Пол.Контрагент КАК Контрагент,
| СУММА(ЕСТЬNULL(ВТ_Пол.Количество1, 0)) КАК Количество1,
| СУММА(ЕСТЬNULL(ВТ_Пол.Сумма1, 0)) КАК Сумма1
|ИЗ
| ВТ_Пол КАК ВТ_Пол
|СГРУППИРОВАТЬ ПО
| ВТ_Пол.Контрагент
Применение ЕСТЬNULL(..., 0) гарантирует, что пустые значения будут интерпретированы как математические нули и корректно сложатся с другими числами в рамках группировки.
Посмотрим на пример, где в группировке участвует поле с типом «Число», например, Доля. Если это поле является результатом вычисления (деления), значения могут отличаться в 10-м знаке после запятой (например, 0.3333333333 и 0.3333333334). В этом случае строки никогда не схлопнутся.
Разберем, как принудительно ограничить точность группировочного поля:
|ВЫБРАТЬ
| ВЫРАЗИТЬ(ВТ_Пол.Доля КАК ЧИСЛО(15, 2)) КАК Доля,
| ВТ_Пол.Контрагент КАК Контрагент,
| СУММА(ВТ_Пол.Сумма1) КАК Сумма1
|ИЗ
| ВТ_Пол КАК ВТ_Пол
|СГРУППИРОВАТЬ ПО
| ВЫРАЗИТЬ(ВТ_Пол.Доля КАК ЧИСЛО(15, 2)),
| ВТ_Пол.Контрагент
Функция ВЫРАЗИТЬ позволяет привести числовые значения к одинаковой разрядности, что делает их идентичными для механизма группировки СУБД.
Если вы применили все вышеуказанные советы, но строки всё равно не объединяются, выполните следующие шаги для диагностики:
СГРУППИРОВАТЬ ПО только одно поле (например, Контрагент). Если строки схлопнулись — значит, проблема в одном из удаленных полей.ТИПЗНАЧЕНИЯ в запросе для проверки.СГРУППИРОВАТЬ ПО, а использовать функцию МАКСИМУМ(Поле) в блоке ВЫБРАТЬ. Это позволит схлопнуть строки, взяв любое из имеющихся значений.Разберем профессиональный подход. Если ваша задача — вывести таблицу, где в колонках стоят периоды, а в строках — контрагенты, ручное написание колонок Сумма1, Сумма2 в запросе является трудоемким и негибким методом. В 1С для этих целей предназначена СКД. В СКД достаточно написать простой запрос, выбирающий детальные записи с полем Период и Сумма. Далее в настройках отчета создается Таблица, где в «Строки» добавляется Контрагент, а в «Колонки» — Период. Система компоновки данных сама выполнит группировку, распределение по столбцам и корректное «схлопывание» всех пустых ячеек без необходимости сложного ручного кодинга в тексте запроса.