Как в запросе 1С получить данные из шапки или табличной части документа в зависимости от вида операции?

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

При разработке отчетов и обработок по кассовым или расчетным документам (например, приходным и расходным кассовым ордерам) часто возникает задача: в зависимости от реквизита ВидОперации необходимо получить либо ровно одну строку с реквизитами из шапки документа, либо детальные строки из его табличной части (расшифровки платежа). Если построить стандартный запрос с простым соединением шапки и табличной части, то для документов, где детализация не требуется, строки шапки все равно размножатся по числу строк таблицы.

Разберем подробно несколько проверенных способов решения этой задачи в платформе 1С:Предприятие.

Способ 1. Объединение запросов через конструкцию ОБЪЕДИНИТЬ ВСЕ

Проанализируем классический подход, предложенный на форуме. Разделим выборку на две независимые части: первая выбирает данные документов, требующих вывода только шапки, а вторая обращается к табличной части документов с детализацией. Затем объединим результаты.

Рассмотрим пример запроса:


ВЫБРАТЬ
    ДокументШапка.Ссылка КАК Документ,
    ДокументШапка.Дата КАК Дата,
    ДокументШапка.Номер КАК Номер,
    ДокументШапка.СуммаДокумента КАК Сумма,
    ДокументШапка.Контрагент КАК Контрагент,
    ДокументШапка.ДоговорКонтрагента КАК Договор,
    0 КАК НомерСтроки
ИЗ
    Документ.ПриходныйКассовыйОрдер КАК ДокументШапка
ГДЕ
    ДокументШапка.ВидОперации = &ВидОперацииБезДетализации
    И ДокументШапка.Проведен = ИСТИНА

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

ВЫБРАТЬ
    ДокументТЧ.Ссылка КАК Документ,
    ДокументТЧ.Ссылка.Дата КАК Дата,
    ДокументТЧ.Ссылка.Номер КАК Номер,
    ДокументТЧ.СуммаПлатежа КАК Сумма,
    ДокументТЧ.Контрагент КАК Контрагент,
    ДокументТЧ.ДоговорКонтрагента КАК Договор,
    ДокументТЧ.НомерСтроки КАК НомерСтроки
ИЗ
    Документ.ПриходныйКассовыйОрдер.РасшифровкаПлатежа КАК ДокументТЧ
ГДЕ
    ДокументТЧ.Ссылка.ВидОперации = &ВидОперацииСДетализацией
    И ДокументТЧ.Ссылка.Проведен = ИСТИНА

Разберем важные правила при построении такого объединения:

  1. Используем строго ОБЪЕДИНИТЬ ВСЕ: Ключевое слово ОБЪЕДИНИТЬ без ВСЕ заставляет СУБД выполнять неявную сортировку и поиск уникальных строк (DISTINCT), что приводит к созданию временных таблиц и резкому падению производительности.
  2. Выравниваем состав и типы полей: Порядок колонок в обеих частях должен быть одинаковым. Если во второй части есть поле НомерСтроки, в первой части задаем значение 0. Если поле отсутствует в одной из веток, типизируем пустое значение, например: ВЫРАЗИТЬ(NULL КАК Справочник.ДоговорыКонтрагентов).

Способ 2. ЛЕВОЕ СОЕДИНЕНИЕ с условием фильтрации в секции ПО

Посмотрим на альтернативный вариант: сформировать единый запрос без объединения веток. Для этого свяжем шапку с табличной частью через ЛЕВОЕ СОЕДИНЕНИЕ, но условие по виду операции вынесем непосредственно в секцию соединения ПО.

Рассмотрим структуру такого запроса:


ВЫБРАТЬ
    Шапка.Ссылка КАК Документ,
    Шапка.Дата КАК Дата,
    ВЫБОР
        КОГДА Шапка.ВидОперации = &ВидОперацииСДетализацией
            ТОГДА ЕСТЬNULL(ТЧ.СуммаПлатежа, 0)
        ИНАЧЕ Шапка.СуммаДокумента
    КОНЕЦ КАК Сумма,
    ВЫБОР
        КОГДА Шапка.ВидОперации = &ВидОперацииСДетализацией
            ТОГДА ТЧ.Контрагент
        ИНАЧЕ Шапка.Контрагент
    КОНЕЦ КАК Контрагент,
    ВЫБОР
        КОГДА Шапка.ВидОперации = &ВидОперацииСДетализацией
            ТОГДА ЕСТЬNULL(ТЧ.НомерСтроки, 0)
        ИНАЧЕ 0
    КОНЕЦ КАК НомерСтроки
ИЗ
    Документ.ПриходныйКассовыйОрдер КАК Шапка
        ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПриходныйКассовыйОрдер.РасшифровкаПлатежа КАК ТЧ
            ПО Шапка.Ссылка = ТЧ.Ссылка
            И Шапка.ВидОперации = &ВидОперацииСДетализацией
ГДЕ
    Шапка.Проведен = ИСТИНА

В этом случае документы с операциями без детализации не будут соединяться со строками табличной части и вернутся в результат ровно одной строкой. Поля выбираются через конструкцию ВЫБОР КОГДА.

Способ 3. Оптимизация через временные таблицы

Если в базе хранится большой объем документов или накладываются сложные фильтры (по периоду, списку организаций, кассам), прямое обращение к табличным частям может вызывать полное сканирование таблицы. Оптимизируем выполнение с помощью пакета запросов:

  1. Первым пакетом отбираем документы во временную таблицу по нужным критериям и обязательно индексируем поле ссылки.
  2. Во втором пакете соединяем временную таблицу с шапкой и табличной частью.

ВЫБРАТЬ
    Документы.Ссылка КАК Ссылка,
    Документы.ВидОперации КАК ВидОперации
ПОМЕСТИТЬ ВТ_ОтобранныеДокументы
ИЗ
    Документ.ПриходныйКассовыйОрдер КАК Документы
ГДЕ
    Документы.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
    И Документы.Проведен = ИСТИНА
ИНДЕКСИРОВАТЬ ПО
    Ссылка;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ.Ссылка КАК Документ,
    ВТ.Ссылка.Дата КАК Дата,
    ВТ.Ссылка.СуммаДокумента КАК Сумма,
    0 КАК НомерСтроки
ИЗ
    ВТ_ОтобранныеДокументы КАК ВТ
ГДЕ
    ВТ.ВидОперации = &ВидОперацииБезДетализации

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

ВЫБРАТЬ
    ТЧ.Ссылка КАК Документ,
    ТЧ.Ссылка.Дата КАК Дата,
    ТЧ.СуммаПлатежа КАК Сумма,
    ТЧ.НомерСтроки КАК НомерСтроки
ИЗ
    ВТ_ОтобранныеДокументы КАК ВТ
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ПриходныйКассовыйОрдер.РасшифровкаПлатежа КАК ТЧ
            ПО ВТ.Ссылка = ТЧ.Ссылка
ГДЕ
    ВТ.ВидОперации = &ВидОперацииСДетализацией

Способ 4. Реализация в Системе компоновки данных (СКД)

При построении отчетов в СКД можно избежать ручного выравнивания полей в тексте единого запроса:

  1. Создаем два независимых набора данных: НаборДанных_Шапка и НаборДанных_ТЧ.
  2. В каждом наборе прописываем собственный запрос и условия по виду операции.
  3. Добавляем Набор данных - объединение и переносим в него оба набора. СКД автоматически выполнит корректную стыковку полей.

Способ 5. Использование регистров конфигурации

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

Если задача заключается в формировании аналитического или финансового отчета, обращение к виртуальным таблицам регистров (например, РегистрБухгалтерии.Хозрасчетный.Обороты или регистрам взаиморасчетов) будет работать быстрее и избавит от необходимости анализировать особенности заполнения табличных частей документов в тексте запроса.

← На главную