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