При работе с Системой Компоновки Данных (СКД) в 1С часто возникает задача объединения информации из разных источников, например, из нескольких регистров, в одной таблице отчета. Это может быть необходимо, когда нам нужно одновременно видеть остатки товаров на складах и доступное количество у поставщиков, или сравнивать плановые и фактические показатели, хранящиеся в различных регистрах. Давайте вместе разберем, как эффективно решить эту проблему, используя различные подходы СКД.
Мы рассмотрим два основных метода, которые позволяют собрать данные из нескольких регистров в единую таблицу отчета, а также углубимся в некоторые продвинутые техники, которые помогут нам добиться максимальной гибкости и производительности.
Один из наиболее гибких и мощных способов собрать данные из разных источников — это использование оператора ОБЪЕДИНИТЬ ВСЕ в запросе. Этот подход позволяет нам формировать несколько независимых выборок данных, а затем объединять их в один общий результат. Ключевое условие для успешного объединения — это совпадение количества и типов полей в каждой из объединяемых выборок.
Рассмотрим подробнее, как это работает:
Формирование запросов для каждого регистра: Сначала мы создаем отдельные запросы для каждого регистра, из которого хотим получить данные. Важно, чтобы у нас было общее поле для группировки, например, Номенклатура.Артикул.
Использование "заглушек" для отсутствующих полей: Поскольку регистры могут иметь разный состав полей (например, в одном есть Количество и Цена, а в другом только Количество), нам необходимо "выровнять" структуру запросов. Для этого мы используем так называемые "заглушки" (0 КАК ИмяПоля, NULL КАК ИмяПоля или пустые строки "" КАК ИмяПоля) для тех полей, которые отсутствуют в одном из подзапросов, но присутствуют в другом. Это гарантирует, что все подзапросы будут иметь одинаковый набор полей с совпадающими типами.
Добавление поля-идентификатора: Чтобы отличить, из какого регистра пришла та или иная строка после объединения, мы можем добавить в каждый подзапрос специальное поле-идентификатор. Например, 1 КАК ТипОстатка для одного регистра и 2 КАК ТипОстатка для другого. Это поле затем можно использовать для группировки или оформления.
Объединение запросов: После подготовки подзапросов мы объединяем их с помощью оператора ОБЪЕДИНИТЬ ВСЕ.
Посмотрим на пример такого запроса:
ВЫБРАТЬ
ОстаткиНаСкладах.Номенклатура.Артикул КАК Артикул,
1 КАК ТипОстатка,
ОстаткиНаСкладах.Склад КАК ОбъектУчета,
ОстаткиНаСкладах.НачальныйОстаток КАК НачальныйОстаток,
ОстаткиНаСкладах.Приход КАК Приход,
ОстаткиНаСкладах.Расход КАК Расход,
ОстаткиНаСкладах.КонечныйОстаток КАК КонечныйОстаток,
0 КАК КоличествоУПоставщика, // Заглушка
0 КАК ЦенаУПоставщика // Заглушка
ИЗ
РегистрНакопления.ОстаткиНаСкладах.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Авто, , ) КАК ОстаткиНаСкладах
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ОстаткиУПоставщиков.Номенклатура.Артикул,
2,
ОстаткиУПоставщиков.Контрагент,
0, // Заглушка
0, // Заглушка
0, // Заглушка
0, // Заглушка
ОстаткиУПоставщиков.Количество КАК КоличествоУПоставщика,
ОстаткиУПоставщиков.Цена КАК ЦенаУПоставщика
ИЗ
РегистрНакопления.ОстаткиУПоставщиков.Остатки(&МоментОтчета, ) КАК ОстаткиУПоставщиков
В этом примере мы объединяем данные из двух регистров. Обратите внимание на использование "заглушек" (0 КАК КоличествоУПоставщика и т.д.) для полей, которые есть только в одном из подзапросов. Поле ТипОстатка поможет нам в дальнейшем различать строки.
Далее в настройках СКД мы можем правильно настроить группировки. Например, мы можем сгруппировать отчет по полю Артикул, а затем по полю ТипОстатка или ОбъектУчета, чтобы сначала вывести остатки по складам, а затем по контрагентам, или наоборот. Для вывода показателей каждого типа остатка в отдельных колонках мы можем использовать условное оформление или группировки колонок.
Другой распространенный подход — это использование ЛЕВОГО СОЕДИНЕНИЯ (LEFT JOIN). Этот метод особенно полезен, когда нам нужно получить все записи из "левой" (основной) таблицы и, если есть совпадения, присоединить к ним соответствующие записи из "правой" таблицы. Если совпадений в правой таблице нет, поля из нее будут иметь значение NULL.
Разберем по шагам, как реализовать левое соединение:
Определение основного набора данных: Выбираем регистр, который будет "левой" таблицей. Чаще всего это тот регистр, по которому мы хотим получить полный список элементов (например, все номенклатурные позиции).
Последовательное соединение регистров: Мы начинаем с выбора ключевого поля (например, Номенклатура), затем присоединяем первый регистр (например, ОстаткиНаСкладах) с помощью ЛЕВОГО СОЕДИНЕНИЯ. После этого к полученному результату присоединяем следующий регистр (например, ОстаткиУПоставщиков) также через ЛЕВОЕ СОЕДИНЕНИЕ.
Выбор полей для вывода: В запросе мы выбираем нужные поля из каждого присоединенного регистра. Например, ОстаткиНаСкладах.КонечныйОстаток КАК СкладКонечныйОстаток и ОстаткиУПоставщиков.Количество КАК ПоставщикКоличество.
Примерная логика запроса может выглядеть так:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Номенклатура,
ОстаткиНаСкладах.КонечныйОстаток КАК ОстатокНаСкладе,
ОстаткиУПоставщиков.Количество КАК КоличествоУПоставщика
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНаСкладах.Остатки(&МоментОтчета, ) КАК ОстаткиНаСкладах
ПО Номенклатура.Ссылка = ОстаткиНаСкладах.Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиУПоставщиков.Остатки(&МоментОтчета, ) КАК ОстаткиУПоставщиков
ПО Номенклатура.Ссылка = ОстаткиУПоставщиков.Номенклатура
Важные моменты при использовании ЛЕВОГО СОЕДИНЕНИЯ в СКД:
Настройка группировок: В настройках СКД мы можем создать группировки по Номенклатура, а затем, если требуется, использовать дополнительные группировки для вывода показателей. Например, можно добавить поле "ЧьихСкладБудет" или "ПризнакСклада", чтобы сначала сгруппировать по типу источника данных, а затем по конкретному складу или контрагенту.
Особенности вычисления итогов: При использовании ЛЕВОГО СОЕДИНЕНИЯ, если в правой таблице нет соответствующих строк, поля из нее будут NULL. Это может влиять на расчет итогов. Если нам нужно вычислить итоги по полям из правой таблицы, которые могут быть NULL, мы можем использовать функции языка выражений СКД, такие как ВычислитьВыражениеСГруппировкойМассив() или ЕСТЬNULL().
Преобразование в ВНУТРЕННЕЕ СОЕДИНЕНИЕ: Если нам нужны только те строки, для которых есть соответствия в обеих таблицах, мы можем наложить отбор на одно из полей правой таблицы, которое гарантированно не будет NULL при наличии соответствия. Это фактически превратит ЛЕВОЕ СОЕДИНЕНИЕ во ВНУТРЕННЕЕ СОЕДИНЕНИЕ.
Наш читатель успешно применил левое соединение, когда требовалось найти только "выбывающие" товары у контрагентов, отбирая их фильтром по приближению к минимальному порогу значения конечного остатка. Это отличный пример того, как гибко можно настроить отчет, комбинируя соединение и отборы.
Помимо основных методов объединения и соединения, существуют дополнительные возможности СКД, которые помогут нам в создании сложных отчетов.
С платформы 1С 8.3.17 появилась мощная возможность передавать в механизм СКД МенеджерВременныхТаблиц. Это позволяет нам создавать временные таблицы программно до начала компоновки отчета и использовать их в запросах наборов данных СКД.
Преимущества МВТ:
Оптимизация производительности: Сложные или повторяющиеся запросы к базе данных можно выполнить один раз, записать результат во временную таблицу, а затем использовать эту таблицу в нескольких наборах данных СКД, значительно сократив нагрузку на СУБД.
Гибкость: Мы можем формировать временные таблицы, используя сложную логику, которую трудно выразить в одном запросе СКД.
Как это работает:
При программном формировании отчетов на СКД, МенеджерВременныхТаблиц инициализируется в методе Инициализировать процессора компоновки данных.
Для того чтобы компоновщик настроек СКД корректно работал с типами данных из временной таблицы, мы рекомендуем явно указывать типы полей в запросе с помощью выражений ВЫРАЗИТЬ(ВТ.ЗначениеПоля КАК <Описание типа>) или ЕСТЬNULL(ВТ.ЗначениеПоля, <Пустое значение такого же типа>).
Пример использования ВЫРАЗИТЬ:
ВЫБРАТЬ
ВТ.Номенклатура,
ВЫРАЗИТЬ(ВТ.Количество КАК ЧИСЛО(15, 3)) КАК Количество
ИЗ
ВременнаяТаблица КАК ВТ
Группировки — это основа построения структуры отчета в СКД. Мы можем создавать:
Группировки по одному или нескольким полям: Например, по Номенклатура, затем по Склад.
Иерархические и подчиненные группировки: Родительская группировка влияет на подчиненные. Например, итоги по складу будут включать итоги по всем номенклатурным позициям на этом складе.
Вертикальные блоки группировок: Для вывода колонок из разных регистров в одной таблице, когда у каждого блока свои показатели, мы можем использовать вертикальные группировки. Это позволяет нам создать сложную структуру отчета, где, например, сначала идут колонки по одному регистру (с группировкой по складам), а затем колонки по другому регистру (с группировкой по контрагентам), и все это в рамках одной общей таблицы.
Пользовательские настройки группировок: Чтобы предоставить пользователям возможность самостоятельно изменять структуру отчета, мы можем выводить группировки в пользовательские настройки.
При работе с объединенными наборами данных важно учитывать особенности наложения отборов. В более ранних версиях платформы (8.3.13 – 8.3.17) могли возникать сложности с наложением отборов на поля, которые отсутствовали в одном из подзапросов объединенного набора. Эта проблема была исправлена в релизе платформы 8.3.18. Если вы сталкиваетесь с подобными сложностями, проверьте версию платформы или режим совместимости.
Для полей с типом Дата в СКД, начиная с версии платформы 8.3.6, реализованы дочерние поля (например, ПериодМесяц, ПериодКвартал), которые позволяют легко получить данные по нужным периодам. Для более ранних версий мы можем использовать пользовательские поля с функцией языка выражений СКД НачалоПериода() для получения требуемой периодичности.
Пример использования НачалоПериода в выражении поля:
НачалоПериода(ДатаДокумента, "Месяц")
Надеемся, что этот подробный разбор поможет вам эффективно работать с группировками и данными из разных регистров в отчетах СКД. Экспериментируйте с различными методами и настройками, чтобы найти оптимальное решение для ваших конкретных задач.
← К списку