Переход от старого ПостроителяОтчета к современной Системе Компоновки Данных (СКД) в 1С v8.3 часто вызывает сложности, особенно когда речь идет об адаптации существующих запросов, корректном расчете агрегированных показателей (например, процентов от общих продаж) и установке предопределенных отборов. Давайте разберем эту задачу по шагам, выяснив, как эффективно использовать возможности СКД для решения подобных проблем.
Когда мы переносим запрос из ПостроителяОтчета в СКД, нам необходимо помнить, что СКД имеет свой собственный, более мощный и гибкий механизм обработки данных. Это означает, что некоторые конструкции, специфичные для ПостроителяОтчета, следует удалить или переосмыслить.
Удаление секции "ИТОГИ" и "ПО"
Важным шагом является удаление секции ИТОГИ и ПО из вашего запроса. ПостроительОтчета использовал их для формирования итоговых строк и группировок. СКД, в свою очередь, предоставляет собственный, гораздо более мощный механизм для построения итогов, группировок и иерархии, который настраивается отдельно в схеме компоновки данных. Если вы оставите эту секцию, при попытке вставить запрос в СКД, система выдаст ошибку или предупреждение, как это случилось в обсуждаемой ситуации. Пользователь форума подтвердил, что именно удаление этих секций помогло адаптировать запрос.
Корректное определение параметров
Убедитесь, что все параметры, которые используются в вашем запросе, такие как &НачПер, &КонПер, &Организация, &Сч9001 и другие, корректно определены в свойствах набора данных схемы компоновки данных. Для каждого параметра необходимо указать его тип, доступность и, при необходимости, предоставить ему значение по умолчанию или связать с пользовательским полем ввода. Если параметры не заданы или заданы неверно, запрос в консоли запросов или в отчете СКД может возвращать пустые данные или ошибаться. Именно с этой проблемой столкнулся автор темы, когда запрос не выводил ничего в консоли.
Работа с временными таблицами и вложенными запросами
СКД прекрасно работает с вложенными запросами и временными таблицами (конструкция ВЫБРАТЬ ... ИЗ (...) КАК ИмяТаблицы). В вашем запросе используется несколько таких конструкций (Sales, PrimeCost, AllSales), что является стандартной практикой и не должно вызывать проблем при адаптации для СКД, если они синтаксически верны. Рассмотрим исходный запрос, чтобы понять его структуру:
ВЫБРАТЬ
Sales.Номенклатура КАК Номенклатура,
Sales.Контрагент КАК Покупатель,
Sales.ДоговорКонтрагента КАК ДоговорКонтрагента,
СУММА(Sales.Количество) КАК Количество,
СУММА(Sales.Сумма) КАК Net_Sales_YTD,
СРЕДНЕЕ(Sales.Цена) КАК Цена,
Sales.Регистратор КАК Регистратор,
ВЫРАЗИТЬ(Sales.Сумма - Sales.Количество * PrimeCost.ЦенаСебест КАК ЧИСЛО(15, 2)) КАК GP1_RUB,
ВЫБОР
КОГДА Sales.Количество * PrimeCost.ЦенаСебест = 0
ТОГДА 0
ИНАЧЕ ВЫРАЗИТЬ(Sales.Сумма * 100 / (Sales.Количество * PrimeCost.ЦенаСебест) - 100 КАК ЧИСЛО(15, 2))
КОНЕЦ КАК GP1_Percent,
PrimeCost.ЦенаСебест КАК ЦенаСебест,
ВЫРАЗИТЬ(Sales.Количество * PrimeCost.ЦенаСебест КАК ЧИСЛО(15, 2)) КАК COGS,
СУММА(ВЫБОР
КОГДА AllSales.Сумма = 0
ТОГДА 0
ИНАЧЕ ВЫРАЗИТЬ(Sales.Сумма / AllSales.Сумма * 100 КАК ЧИСЛО(15, 2))
КОНЕЦ) КАК Bayers_Share_In_Total_Net_Sales
ИЗ
(ВЫБРАТЬ
ХозрасчетныйОборотыДтКт.СубконтоКт3 КАК Номенклатура,
ХозрасчетныйОборотыДтКт.СубконтоДт1 КАК Контрагент,
ХозрасчетныйОборотыДтКт.СубконтоДт2 КАК ДоговорКонтрагента,
ХозрасчетныйОборотыДтКт.КоличествоОборотКт КАК Количество,
ХозрасчетныйОборотыДтКт.СуммаОборот КАК Сумма,
ВЫБОР
КОГДА ХозрасчетныйОборотыДтКт.КоличествоОборотКт = 0
ТОГДА 0
ИНАЧЕ ВЫРАЗИТЬ(ЕСТЬNULL(ХозрасчетныйОборотыДтКт.СуммаОборот, 0) / ХозрасчетныйОборотыДтКт.КоличествоОборотКт КАК ЧИСЛО(15, 2))
КОНЕЦ КАК Цена,
ХозрасчетныйОборотыДтКт.Регистратор КАК Регистратор
ИЗ
РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(&НачПер, &КонПер, Регистратор, , , СчетКт = &Сч9001, , Организация = &Организация) КАК ХозрасчетныйОборотыДтКт) КАК Sales
ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
ХозрасчетныйОборотыДтКт.КоличествоОборотКт КАК Количество,
ХозрасчетныйОборотыДтКт.СуммаОборот КАК Сумма,
ХозрасчетныйОборотыДтКт.СубконтоКт1 КАК Номенклатура,
ВЫБОР
КОГДА ХозрасчетныйОборотыДтКт.КоличествоОборотКт = 0
ТОГДА 0
ИНАЧЕ ХозрасчетныйОборотыДтКт.СуммаОборот / ХозрасчетныйОборотыДтКт.КоличествоОборотКт
КОНЕЦ КАК ЦенаСебест
ИЗ
РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(
&НачПер,
&КонПер,
Период,
СчетДт = &Сч9002
ИЛИ СчетДт = &Сч9102,
,
СчетКт = &Сч43
ИЛИ СчетКт = &Сч4101
ИЛИ СчетКт = &Сч4104
ИЛИ СчетКт = &Сч10,
,
Организация = &Организация) КАК ХозрасчетныйОборотыДтКт) КАК PrimeCost
ПО Sales.Номенклатура = PrimeCost.Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
СУММА(ХозрасчетныйОборотыДтКт.СуммаОборот) КАК Сумма
ИЗ
РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(&НачПер, &КонПер, Регистратор, , , СчетКт = &Сч9001, , Организация = &Организация) КАК ХозрасчетныйОборотыДтКт) КАК AllSales
ПО (ИСТИНА)
СГРУППИРОВАТЬ ПО
Sales.Номенклатура,
Sales.Контрагент,
Sales.ДоговорКонтрагента,
Sales.Регистратор,
PrimeCost.ЦенаСебест,
ВЫРАЗИТЬ(Sales.Сумма - Sales.Количество * PrimeCost.ЦенаСебест КАК ЧИСЛО(15, 2)),
ВЫБОР
КОГДА Sales.Количество * PrimeCost.ЦенаСебест = 0
ТОГДА 0
ИНАЧЕ ВЫРАЗИТЬ(Sales.Сумма * 100 / (Sales.Количество * PrimeCost.ЦенаСебест) - 100 КАК ЧИСЛО(15, 2))
КОНЕЦ,
ВЫРАЗИТЬ(Sales.Количество * PrimeCost.ЦенаСебест КАК ЧИСЛО(15, 2))
ИТОГИ
СУММА(Количество),
СУММА(Net_Sales_YTD),
СРЕДНЕЕ(Цена),
СУММА(GP1_RUB),
СРЕДНЕЕ(GP1_Percent),
СРЕДНЕЕ(ЦенаСебест),
СУММА(COGS),
СУММА(Bayers_Share_In_Total_Net_Sales)
ПО
ОБЩИЕ,
Покупатель
Как мы видим, этот запрос содержит все упомянутые элементы. В СКД нам потребуется удалить секцию ИТОГИ ... ПО ... и, как мы увидим далее, подзапрос AllSales.
Основная проблема, с которой столкнулся автор темы, заключалась в неверном расчете процента от общих продаж при применении отборов. Процент считался от "истинного" общего итога по всем данным, а не от "отфильтрованного" итога, то есть от тех данных, которые попали в отчет после применения отбора. СКД позволяет легко решить эту проблему благодаря своим мощным возможностям агрегации.
Удаление подзапроса AllSales и условия ПО (ИСТИНА)
В исходном запросе для получения общей суммы используется подзапрос AllSales и странное условие соединения ПО (ИСТИНА). Этот подзапрос извлекает сумму продаж по всем данным без учета потенциальных отборов, которые могут быть применены в пользовательском интерфейсе. В СКД такой подход не только избыточен, но и неверен для расчета процента от фильтрованного итога. СКД способна самостоятельно вычислить общий итог по текущему набору данных, который уже включает все примененные отборы. Поэтому мы рекомендуем удалить подзапрос AllSales и соответствующее левое соединение из текста запроса, который будет использоваться в СКД.
Создание вычисляемого поля в СКД
Чтобы получить процент от общего итога по отфильтрованным данным, необходимо создать вычисляемое поле непосредственно в СКД, а не пытаться реализовать это в тексте запроса. Давайте рассмотрим, как это сделать:
В настройках схемы компоновки данных перейдите на вкладку "Вычисляемые поля".
Добавьте новое вычисляемое поле, например, с именем ПроцентОтОбщихПродаж.
В качестве выражения для этого поля укажите следующую формулу:
Сумма(Net_Sales_YTD) / СУММА(Net_Sales_YTD) ОБЩИЙ ИТОГ * 100
Разберем эту формулу:
Сумма(Net_Sales_YTD) будет возвращать сумму продаж для текущей строки или группы, в зависимости от группировки отчета.СУММА(Net_Sales_YTD) ОБЩИЙ ИТОГ (или SUM(Net_Sales_YTD) TOTAL в англоязычных конфигурациях) — это специальная агрегатная функция СКД, которая возвращает сумму по всему набору данных после применения всех отборов. Таким образом, эта функция всегда будет учитывать только те данные, которые видны в отчете.При использовании такого вычисляемого поля, процент будет всегда рассчитываться относительно суммы, видимой в отчете, и при любом отборе сумма процентов по всему отчету (или по каждой крупной группе, если так настроено) будет составлять 100%.
Автор темы также интересовался, как сделать так, чтобы отчет всегда формировался с отбором по определенной группе номенклатуры без участия пользователя, то есть с предопределенным или "жестким" отбором. СКД предоставляет удобные инструменты для такой настройки.
Настройка фиксированного отбора
В режиме конфигурирования (или в пользовательском режиме, если это разрешено и сохраняется), в настройках схемы компоновки данных перейдите на вкладку "Настройки" или "Основные настройки". Здесь вы можете добавить новый элемент отбора. Пользователь форума также получил подтверждение, что это возможно сделать в настройках СКД.
Условие отбора по группе
Для поля Номенклатура выберите тип сравнения В группе из списка (или просто В группе, в зависимости от версии платформы). В качестве значения укажите нужную группу номенклатуры (например, "net sales film") из справочника. Это позволит отобрать все элементы, находящиеся в указанной группе и ее подгруппах.
Включение иерархии
Если необходимо, чтобы отбор включал элементы из подгрупп, убедитесь, что для поля "Номенклатура" в СКД включена иерархия. Это обычно настраивается в свойствах поля на вкладке "Наборы данных" или "Поля". Включив иерархию, вы гарантируете, что при отборе по группе будут учтены все вложенные элементы и подгруппы.
Фиксированные настройки против пользовательских
Если вы хотите, чтобы пользователь видел этот отбор, но не мог его изменять, вы можете добавить его в "Пользовательские настройки" с ограничением редактирования. Однако, если отбор должен быть "жестким" и невидимым для изменения пользователем, его лучше оставить в фиксированных настройках схемы. В этом случае отчет будет всегда формироваться с этим отбором автоматически, без дополнительных действий со стороны пользователя.
Следуя этим шагам, вы сможете успешно перевести ваш отчет с ПостроителяОтчета на СКД, корректно настроить расчет процентов отфильтрованных данных и установить необходимые предопределенные отборы, значительно повысив гибкость и функциональность вашего отчета.