Как объединить данные из нескольких регистров в одном запросе 1С?

Программист 1С v8.3 (Управляемые формы) Управленческий учет IT и автоматизация бизнеса
← На главную

В практике разработчика 1С часто возникает задача собрать данные из разных источников в одну итоговую таблицу. Типичный пример: необходимо получить отчет, в котором будут отображены и движения товаров по складу, и оказанные услуги. Поскольку это разные сущности, они хранятся в разных регистрах накопления. Рассмотрим подробнее, как правильно свести эти данные в один запрос, избежать дублей и обеспечить высокую производительность системы.

Метод 1. Использование оператора ОБЪЕДИНИТЬ ВСЕ

Самый простой и логичный способ — это использование механизма объединения таблиц. В языке запросов 1С для этого предназначен оператор ОБЪЕДИНИТЬ ВСЕ. Основное правило здесь: количество колонок и их порядок в каждом подзапросе должны полностью совпадать.

Разберем по шагам, как составить такой запрос на примере регистров "ОстаткиТоваров" и "Услуги":


ВЫБРАТЬ
    ОстаткиТоваров.Товар КАК Номенклатура,
    ОстаткиТоваров.КоличествоОборот КАК Количество,
    ОстаткиТоваров.СуммаОборот КАК Сумма
ИЗ
    РегистрНакопления.ОстаткиТоваров.Обороты(&НачалоПериода, &КонецПериода) КАК ОстаткиТоваров

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Услуги.Услуга,
    Услуги.КоличествоОборот,
    Услуги.СуммаОборот
ИЗ
    РегистрНакопления.Услуги.Обороты(&НачалоПериода, &КонецПериода) КАК Услуги

Проанализируем ситуацию с именами полей. Обратите внимание, что в первом запросе мы использовали псевдоним КАК Номенклатура. Во втором запросе имена полей могут отличаться (например, "Услуга" вместо "Товар"), но система 1С автоматически сопоставит их по порядковому номеру колонки. Итоговая таблица будет иметь заголовки из первого запроса.

Метод 2. Группировка объединенных данных

Если один и тот же товар или услуга присутствуют в обоих регистрах (или в одном регистре, но в разных строках), после объединения они выведутся отдельными строками. Чтобы "схлопнуть" результат, необходимо применить группировку. Однако, начинающие разработчики часто совершают ошибку, пытаясь вставить СГРУППИРОВАТЬ ПО внутри одной из частей объединения.

Правильный подход заключается в использовании вложенного запроса. Посмотрим на пример структуры такого запроса:


ВЫБРАТЬ
    ВложенныйЗапрос.Номенклатура КАК Номенклатура,
    СУММА(ВложенныйЗапрос.Количество) КАК Количество,
    СУММА(ВложенныйЗапрос.Сумма) КАК Сумма
ИЗ
    (ВЫБРАТЬ
        Остатки.Товар КАК Номенклатура,
        Остатки.КоличествоОборот КАК Количество,
        Остатки.СуммаОборот КАК Сумма
    ИЗ
        РегистрНакопления.ОстаткиТоваров.Обороты(&НачалоПериода, &КонецПериода) КАК Остатки
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        Услуги.Услуга,
        Услуги.Количество,
        Услуги.Сумма
    ИЗ
        РегистрНакопления.Услуги.Обороты(&НачалоПериода, &КонецПериода) КАК Услуги) КАК ВложенныйЗапрос

СГРУППИРОВАТЬ ПО
    ВложенныйЗапрос.Номенклатура

Выясним причину, почему это важно: оператор СГРУППИРОВАТЬ ПО во внешнем запросе обработает уже весь массив данных, полученный от объединения, и корректно просуммирует ресурсы Количество и Сумма.

Метод 3. Использование "заглушек" для несовпадающих колонок

Иногда требуется выводить колонки, которые есть только в одном из регистров. Например, в регистре "Остатки" есть поле "Склад", а в "Услугах" его нет. В этом случае мы должны вставить пустую "заглушку" в ту таблицу, где данные отсутствуют. Проанализируем ситуацию: в качестве заглушек для чисел лучше использовать 0, а для ссылочных типов — ЗНАЧЕНИЕ(Справочник.ИмяСправочника.ПустаяСсылка) или NULL.

Пример использования заглушек:


ВЫБРАТЬ
    Остатки.Товар КАК Номенклатура,
    Остатки.Склад КАК Склад,
    Остатки.КоличествоОборот КАК Количество
ИЗ
    РегистрНакопления.ОстаткиТоваров.Обороты() КАК Остатки

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Услуги.Услуга,
    ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка),
    Услуги.КоличествоОборот
ИЗ
    РегистрНакопления.Услуги.Обороты() КАК Услуги

Важные рекомендации по оптимизации

Для создания качественных и быстрых отчетов рассмотрим подробнее несколько профессиональных приемов:

  1. Работа с виртуальными таблицами: Всегда обращайтесь к таблицам .Обороты или .ОстаткиИОбороты вместо физических таблиц регистра. Это позволяет платформе использовать заранее рассчитанные итоги.
  2. Параметры виртуальных таблиц: Устанавливайте фильтры по периоду и измерениям (например, по номенклатуре) непосредственно в параметрах виртуальной таблицы: Обороты(&Начало, &Конец, , Товар = &ВыбТовар). Это значительно ускоряет выполнение, так как данные отсекаются на уровне СУБД.
  3. Временные таблицы: Если запрос становится слишком сложным, используйте МенеджерВременныхТаблиц. Сначала поместите данные из первого регистра во временную таблицу ВТ_Товары, данные из второго — в ВТ_Услуги, а затем объедините их в финальном шаге. Это упрощает отладку и чтение кода.
  4. Различие ОБЪЕДИНИТЬ и ОБЪЕДИНИТЬ ВСЕ: По умолчанию используйте ОБЪЕДИНИТЬ ВСЕ. Обычный оператор ОБЪЕДИНИТЬ выполняет дополнительную проверку на уникальность каждой строки, что замедляет работу системы.

Таким образом, мы выяснили, что сведение данных из разных регистров — это стандартная задача, решаемая через объединение выборок. Помните, что правильная типизация полей и использование виртуальных таблиц — залог стабильной работы вашего кода в высоконагруженных базах данных.

← На главную