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