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