При разработке отчетов в Системе компоновки данных (СКД) программисты часто сталкиваются с тем, что система «схлопывает» строки, которые должны выводиться отдельно. Классический пример — отчет по заказам клиентов, где одна и та же номенклатура может быть продана в рамках одного документа по разным ценам или разными строками. СКД по умолчанию стремится сгруппировать такие позиции и просуммировать их количество и цену, что приводит к искажению данных.
В этой статье мы подробно разберем, почему это происходит, и проанализируем пять эффективных способов решения этой проблемы: от использования детальных записей до тонкой настройки ресурсов и составных группировок.
Рассмотрим реальный запрос, с которым возникла проблема в конфигурации «1С:Управление торговлей 11»:
ВЫБРАТЬ
ЗаказКлиентаТовары.Ссылка КАК Заказ,
ВЫБОР
КОГДА ЗаказКлиентаТовары.Ссылка.СпособДоставки = ЗНАЧЕНИЕ(Перечисление.СпособыДоставки.СиламиПеревозчика)
ТОГДА ЗаказКлиентаТовары.Ссылка.ПеревозчикПартнер
ИНАЧЕ ""
КОНЕЦ КАК Доставка,
ЗаказКлиентаТовары.Ссылка.Контрагент КАК Контрагент,
ЗаказКлиентаТовары.Номенклатура.Артикул КАК Артикул,
ЗаказКлиентаТовары.Номенклатура КАК Номенклатура,
ВЫРАЗИТЬ(ЗаказКлиентаТовары.Количество КАК ЧИСЛО(10, 0)) КАК Количество,
ВЫРАЗИТЬ(ЗаказКлиентаТовары.Цена КАК ЧИСЛО(10, 2)) КАК ЦенаПродажи,
ВЫРАЗИТЬ(ЦеныНоменклатурыПоставщиковСрезПоследних.Цена КАК ЧИСЛО(10, 2)) КАК ЦенаЗакупки,
ЗаказКлиентаТовары.Ссылка.Комментарий КАК Комментарий,
ЗаказКлиентаТовары.НомерСтроки КАК НомерСтроки
ИЗ
Документ.ЗаказКлиента.Товары КАК ЗаказКлиентаТовары
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатурыПоставщиков.СрезПоследних КАК ЦеныНоменклатурыПоставщиковСрезПоследних
ПО ЗаказКлиентаТовары.Номенклатура = ЦеныНоменклатурыПоставщиковСрезПоследних.Номенклатура
ГДЕ
ЗаказКлиентаТовары.Ссылка.Проведен
И ЗаказКлиентаТовары.Ссылка.Дата МЕЖДУ &НачалоПериода И &КонецПериода
В данном запросе выбираются позиции из табличной части товаров заказа клиента. Обратите внимание, что здесь присутствует поле НомерСтроки. Если в настройках СКД настроить простую группировку, например, по полю Номенклатура, то позиции с одинаковым товаром, но с разной ценой, объединятся, а их показатели количества просуммируются. Что еще хуже — СКД может попытаться просуммировать и саму цену продажи, если она ошибочно добавлена в ресурсы. Выясним, как заставить систему выводить эти строки обособленно.
Самый простой и логичный способ вывести строки запроса в СКД «как есть» (без какого-либо сворачивания и агрегации) — это использование специального элемента структуры компоновки под названием <Детальные записи>.
Разберем этот процесс по шагам:
<Детальные записи>.Номенклатура, ЦенаПродажи, Количество, Доставка и другие.При таком подходе СКД полностью отключает внутренние механизмы группировки для этого уровня и выводит каждую строку из результата запроса ровно в том виде, в котором её вернула СУБД.
Часто бизнес-требования диктуют необходимость группировать данные (например, по контрагенту или заказу), но внутри этой группировки строки с разной ценой не должны объединяться. Если мы просто добавим группировку по Номенклатура, а внутри нее сделаем подчиненную группировку по цене, отчет станет неудобным для чтения — пользователю придется раскрывать бесконечные «плюсики» иерархии.
Решением этой проблемы является создание составной группировки. Рассмотрим подробнее, как её настроить:
Номенклатура, а затем вторым полем — ЦенаПродажи.Если вам необходимо гарантировать, что абсолютно все строки табличной части документа будут выведены отдельно (даже если у них полностью совпадают и номенклатура, и цена), необходимо использовать уникальный идентификатор строки.
В представленном выше запросе уже выбирается поле ЗаказКлиентаТовары.НомерСтроки КАК НомерСтроки. Поскольку номер строки внутри табличной части конкретного документа всегда уникален, мы можем использовать его в качестве ключа группировки:
НомерСтроки в список полей вашей группировки на вкладке Настройки.Номенклатура, ЦенаПродажи и Заказ.Одной из частых причин нежелательного суммирования является автоматическое или ошибочное добавление числовых полей на вкладку Ресурсы схемы компоновки данных. По умолчанию СКД пытается применить функцию СУММА() ко всем числовым полям.
Выясним, как правильно настроить ресурсы в нашем случае:
ЦенаПродажи и ЦенаЗакупки не должны находиться на вкладке «Ресурсы», если для них настроена функция СУММА(). Удалите их оттуда. Цены должны оставаться простыми реквизитами группировки или детальных записей.СУММА() на более подходящие: СРЕДНЕЕ(), МАКСИМУМ() или МИНИМУМ().Заказ, но игнорировалось и не суммировалось на уровне детальных записей.Когда в запросе СКД используются левые соединения (как в нашем примере с регистром сведений ЦеныНоменклатурыПоставщиков.СрезПоследних), оптимизатор СКД может попытаться упростить запрос перед отправкой в СУБД. Это иногда приводит к неожиданному «схлопыванию» результатов.
Чтобы жестко зафиксировать вывод ключевых полей, проанализируем настройки вкладки Набор данных:
Заказ, Номенклатура или НомерСтроки).Этот флаг сообщает компоновщику данных, что указанные поля всегда должны присутствовать в итоговом SQL-запросе, независимо от того, выбрал их пользователь в настройках отчета или нет. Это гарантирует сохранение структуры исходной выборки и предотвращает нежелательную оптимизацию (сворачивание) строк.
Используя предложенные методы, мы можем гибко управлять выводом информации в СКД, получая именно те отчеты, которые ожидают конечные пользователи, без дублирования или некорректного суммирования цен.