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