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