Объединение двух запросов в 1С:Предприятие — одна из самых востребованных операций при работе с данными. Без этого навыка сложно обойтись, когда нужно получить единый отчёт из разных источников, сравнить данные за периоды или скомбинировать результаты из нескольких таблиц. Однако начинающие разработчики часто сталкиваются с ошибками: от синтаксических до логических, когда объединённые данные дублируются или теряются.
В этой статье разберём 5 рабочих методов объединения запросов — от простого UNION до сложных конструкций с временными таблицами. Каждый способ проиллюстрирован реальными примерами кода, которые можно сразу использовать в своих конфигурациях. Особое внимание уделим нюансам производительности: почему некоторые запросы тормозят на больших объёмах данных и как этого избежать.
Если вы работаете с 1С 8.3 или 1С 8.2, все приведённые решения будут актуальны — различия в синтаксисе минимальны. А для тех, кто только осваивает язык запросов, в конце статьи есть FAQ с ответами на типичные ошибки.
1. Метод UNION: простое объединение результатов
Самый очевидный способ объединить два запроса — оператор UNION. Он позволяет "склеить" результаты двух независимых запросов в одну таблицу. Главное правило: структура выборок должна совпадать — одинаковое количество колонок и совместимые типы данных.
Пример: объединим список клиентов из справочника Контрагенты и список поставщиков из документа ПоступлениеТоваров:
ВЫБРАТЬ
Контрагенты.Ссылка КАК Клиент,
Контрагенты.Наименование КАК Имя
ИЗ
Справочник.Контрагенты КАК Контрагенты
ГДЕ
Контрагенты.ЭтоГруппа = ЛОЖЬ
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ПоступлениеТоваров.Контрагент КАК Клиент,
ПоступлениеТоваров.Контрагент.Наименование КАК Имя
ИЗ
Документ.ПоступлениеТоваров КАК ПоступлениеТоваров
Обратите внимание на ключевое слово ВСЕ — оно сохраняет все дубликаты. Если нужно убрать повторяющиеся строки, используйте просто ОБЪЕДИНИТЬ (без ВСЕ). Но помните: это может значительно замедлить выполнение на больших объёмах данных.
- ✅ Плюсы: простой синтаксис, работает во всех версиях 1С.
- ⚠️ Минусы: не подходит для объединения по условию (например, "объединить только те строки, где совпадает дата").
- 🔹 Когда использовать: когда нужно просто слить два набора данных без дополнительной логики.
Если в объединённых запросах есть колонки с одинаковыми именами, но разными данными (например, Сумма из одного запроса и Сумма из другого), обязательно переименуйте их с помощью КАК, чтобы избежать путаницы.
2. Подзапросы: объединение с условием
Если нужно объединить данные не "в лоб", а по какому-то правилу (например, только те записи, которые есть в обоих запросах), используйте подзапросы. Это гибкий инструмент, который позволяет реализовать логику типа IN, EXISTS или NOT EXISTS.
Пример: найдём товары, которые есть и в справочнике Номенклатура, и в документе РеализацияТоваров за текущий месяц:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Товар,
Номенклатура.Наименование КАК Название
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.Ссылка В (
ВЫБРАТЬ
РеализацияТоваров.Номенклатура
ИЗ
Документ.РеализацияТоваров КАК РеализацияТоваров
ГДЕ
МЕСЯЦ(РеализацияТоваров.Дата) = МЕСЯЦ(ТЕКУЩАЯДАТА())
)
В этом примере внутренний запрос возвращает список товаров из реализаций, а внешний — проверяет, есть ли эти товары в справочнике. Такой подход полезен для фильтрации данных по сложным условиям.
⚠️ Внимание: Подзапросы сEXISTSчасто работают быстрее, чемIN, особенно если внутренний запрос возвращает много строк. Пример:ГДЕ СУЩЕСТВУЕТ (ВЫБРАТЬ ...).
| Метод | Когда использовать | Производительность |
|---|---|---|
UNION |
Простое слияние двух наборов данных | ⭐⭐⭐⭐ (быстро, если нет дублей) |
Подзапрос с IN |
Фильтрация по списку значений | ⭐⭐ (медленно на больших списках) |
Подзапрос с EXISTS |
Проверка существования связанных данных | ⭐⭐⭐⭐⭐ (оптимально для сложных условий) |
3. Временные таблицы: для сложных объединений
Когда нужно объединить данные с промежуточной обработкой (например, посчитать агрегаты, отфильтровать, а потом соединить), на помощь приходят временные таблицы. Они позволяют разбить сложный запрос на этапы и избежать громоздких конструкций.
Пример: сначала соберём данные о продажах по регионам, а потом объединим их с данными о остатках на складах:
// Сначала создаём временную таблицу с продажами
ВЫБРАТЬ
Регион.Наименование КАК Регион,
СУММА(Реализация.СуммаДокумента) КАК Продажи
ПОМЕСТИТЬ втПродажи
ИЗ
Документ.РеализацияТоваров КАК Реализация
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Регионы КАК Регион
ПО Реализация.Регион = Регион.Ссылка
СГРУППИРОВАТЬ ПО
Регион.Наименование
ИНДЕКСИРОВАТЬ ПО
Регион
;
// Теперь объединяем с остатками
ВЫБРАТЬ
втПродажи.Регион КАК Регион,
втПродажи.Продажи,
Остатки.ОстатокКоличество КАК Остаток
ИЗ
втПродажи КАК втПродажи
ЛЕВОЕ СОЕДИНЕНИЕ (
ВЫБРАТЬ
РегионыОстатки.Регион КАК Регион,
СУММА(РегистрыНакопления.ОстаткиТоваров.КоличествоОстаток) КАК ОстатокКоличество
ИЗ
РегистрНакопления.ОстаткиТоваров КАК РегистрыНакопления.ОстаткиТоваров
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Регионы КАК РегионыОстатки
ПО РегистрыНакопления.ОстаткиТоваров.Склад.Регион = РегионыОстатки.Ссылка
СГРУППИРОВАТЬ ПО
РегионыОстатки.Регион
) КАК Остатки
ПО втПродажи.Регион = Остатки.Регион
В этом примере мы сначала сохраняем агрегированные данные о продажах во временную таблицу втПродажи, а потом соединяем её с данными об остатках. Такой подход значительно ускоряет выполнение на больших базах, так как промежуточные результаты не пересчитываются многократно.
- 📌 Совет: Всегда индексируйте временные таблицы по ключевым полям (как в примере с
ИНДЕКСИРОВАТЬ ПО Регион). Это ускорит последующие соединения. - 🔄 Альтернатива: Вместо временных таблиц можно использовать
ОБЪЕДИНЕНИЕ ЗАПРОСОВ(см. следующий раздел), но они менее гибкие.
4. Объединение запросов (ОБЪЕДИНЕНИЕ ЗАПРОСОВ)
В 1С:Предприятие 8.3 появилась специальная конструкция — ОБЪЕДИНЕНИЕ ЗАПРОСОВ. Она позволяет объединить несколько запросов в один результат, при этом каждый запрос может иметь свою структуру (в отличие от UNION, где колонки должны совпадать).
Пример: объединим данные о клиентах и их заказах, где у клиентов и заказов разные поля:
ОБЪЕДИНЕНИЕ ЗАПРОСОВ
ВЫБРАТЬ
"Клиент" КАК Тип,
Контрагенты.Ссылка КАК Ссылка,
Контрагенты.Наименование КАК Наименование,
"" КАК Дата,
"" КАК Сумма
ИЗ
Справочник.Контрагенты КАК Контрагенты
ГДЕ
Контрагенты.ЭтоГруппа = ЛОЖЬ,
ВЫБРАТЬ
"Заказ" КАК Тип,
ЗаказыКлиентов.Клиент КАК Ссылка,
ЗаказыКлиентов.Клиент.Наименование КАК Наименование,
ЗаказыКлиентов.Дата КАК Дата,
ЗаказыКлиентов.СуммаДокумента КАК Сумма
ИЗ
Документ.ЗаказКлиента КАК ЗаказыКлиентов
КОНЕЦ ОБЪЕДИНЕНИЯ
Здесь мы формируем единый результат, где строки с типом "Клиент" содержат данные из справочника, а строки с типом "Заказ" — данные из документов. Это удобно для построения универсальных отчётов, где нужно показать разные сущности в одной таблице.
⚠️ Внимание: Если в объединённых запросах есть колонки с одинаковыми именами, но разными типами данных (например, Дата как дата в одном запросе и как строка в другом), 1С выдаст ошибку. Всегда проверяйте совместимость типов!
5. Соединение таблиц (JOIN): альтернатива объединению
Иногда задачу "объединения" можно решить без UNION или временных таблиц — достаточно правильно использовать соединения таблиц (JOIN). Например, если нужно получить данные из двух таблиц, где есть общий ключ (например, Контрагент), проще сделать СОЕДИНЕНИЕ, чем объединять результаты отдельных запросов.
Пример: получим список клиентов и их заказы за последний месяц:
ВЫБРАТЬ
Контрагенты.Наименование КАК Клиент,
Заказы.Дата КАК ДатаЗаказа,
Заказы.СуммаДокумента КАК Сумма
ИЗ
Справочник.Контрагенты КАК Контрагенты
ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента КАК Заказы
ПО Контрагенты.Ссылка = Заказы.Клиент
ГДЕ
Заказы.Дата >= НАЧАЛОМЕСЯЦА(ТЕКУЩАЯДАТА())
Здесь мы не объединяем два запроса, а сразу соединяем таблицы по ключу. Это более эффективный способ, если:
- 🔗 Есть явная связь между таблицами (например,
Контрагент → Заказы). - 📊 Нужно получить данные в виде "одна строка на связку" (а не "все строки из обоих запросов").
- ⚡ Требуется максимальная производительность (соединения обычно быстрее, чем
UNION+ постобработка).
Когда использовать UNION вместо JOIN?
UNION нужен, когда нужно слить два независимых набора данных, которые не связаны друг с другом по ключам. Например:
- Объединить список активных и архивных клиентов (они хранятся в разных таблицах без прямой связи).
- Слить результаты двух разных отчётов в один.
- Получить все уникальные значения из двух полей (например, все города из справочника клиентов и всех городов из справочника поставщиков).
6. Оптимизация объединённых запросов
Объединение запросов может значительно замедлить работу системы, если не следить за производительностью. Вот ключевые правила оптимизации:
- Избегайте
UNIONбезВСЕна больших данных.
Удаление дублей (
ОБЪЕДИНИТЬвместоОБЪЕДИНИТЬ ВСЕ) требует дополнительных ресурсов. Если дубли не критичны, используйтеВСЕ. - Индексируйте временные таблицы.
Всегда добавляйте
ИНДЕКСИРОВАТЬ ПОдля полей, по которым потом будете соединять таблицы. - Разбивайте сложные запросы на части.
Вместо одного гигантского запроса с 10-ю объединениями лучше использовать временные таблицы или
ОБЪЕДИНЕНИЕ ЗАПРОСОВ. - Используйте
EXISTSвместоIN.
Подзапросы с
EXISTSобычно работают быстрее, особенно если внутренний запрос возвращает много строк.
Пример оптимизированного запроса с временными таблицами:
// Шаг 1: Получаем уникальных клиентов
ВЫБРАТЬ РАЗЛИЧНЫЕ
Контрагенты.Ссылка КАК Клиент
ПОМЕСТИТЬ втКлиенты
ИЗ
Справочник.Контрагенты КАК Контрагенты
ГДЕ
Контрагенты.ЭтоГруппа = ЛОЖЬ
ИНДЕКСИРОВАТЬ ПО
Клиент
;
// Шаг 2: Получаем их заказы
ВЫБРАТЬ
втКлиенты.Клиент КАК Клиент,
Заказы.Дата КАК ДатаЗаказа,
Заказы.СуммаДокумента КАК Сумма
ИЗ
втКлиенты КАК втКлиенты
ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента КАК Заказы
ПО втКлиенты.Клиент = Заказы.Клиент
В этом примере мы сначала сокращаем список клиентов до уникальных, а потом соединяем их с заказами. Это в разы быстрее, чем объединение всех клиентов и всех заказов в одном запросе.
Всегда тестируйте производительность объединённых запросов на реальных данных! То, что быстро работает на тестовой базе с 100 записями, может "подвесить" боевую систему с миллионом строк.
FAQ: Ответы на частые вопросы
Можно ли объединить запросы с разным количеством колонок?
Нет, для UNION количество и типы колонок должны совпадать. Если структуры разные, используйте ОБЪЕДИНЕНИЕ ЗАПРОСОВ (доступно в 1С 8.3+) или дополните недостающие колонки пустыми значениями (например, "" КАК ПустоеПоле).
Почему мой запрос с UNION работает очень медленно?
Чаще всего тормоза возникают из-за:
- Удаления дублей (используйте
UNION ALLвместоUNION, если дубли не критичны). - Отсутствия индексов на полях соединения.
- Слишком большого объёма данных (разбейте запрос на части с временными таблицами).
Проверьте план выполнения запроса в Консоли запросов (меню Все функции → План запроса).
Как объединить данные из двух разных баз 1С?
Для объединения данных из разных баз используйте:
- Распределённые информационные базы (РИБ). Настройте обмен данными и синхронизацию.
- HTTP-сервисы или REST API. Запрашивайте данные из одной базы и загружайте в другую.
- Внешние источники данных (для 1С 8.3.14+). Подключите вторую базу как внешний источник и выполняйте запросы к ней напрямую.
Пример подключения внешней базы:
ПодключитьВнешнююБазу("File=C:\Bases\Base2;Usr=Администратор;Pwd=123");
Можно ли в одном запросе использовать UNION и JOIN одновременно?
Да, это допустимо. Например, можно сначала объединить два набора данных с помощью UNION, а потом соединить результат с третьей таблицей:
ВЫБРАТЬ
ОбъединённыеДанные.Поле1,
ТретьяТаблица.Поле2
ИЗ
(
ВЫБРАТЬ Поле1 ИЗ Таблица1
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ Поле1 ИЗ Таблица2
) КАК ОбъединённыеДанные
ЛЕВОЕ СОЕДИНЕНИЕ ТретьяТаблица КАК ТретьяТаблица
ПО ОбъединённыеДанные.Поле1 = ТретьяТаблица.Связь
Как объединить запросы с разными типами данных в колонках?
Если в объединённых запросах есть колонки с одинаковыми именами, но разными типами (например, Число и Строка), 1С выдаст ошибку. Решения:
- Переименуйте колонки с помощью
КАК. - Приведите типы к общему (например,
СТРОКА(ЧисловоеПоле) КАК ТекстовоеПоле). - Используйте
ОБЪЕДИНЕНИЕ ЗАПРОСОВ, где колонки могут отличаться.