Как правильно соединить данные регистра накопления и табличной части в запросе 1С?

Программист 1С v8.3 (Управляемые формы) 1С:Управление нашей фирмой Управленческий учет Промышленность, строительство и АПК
← На главную

При разработке отчетов в системе 1С, особенно в таких конфигурациях, как 1С:Управление нашей фирмой (УНФ), часто возникает задача сопоставления фактических данных из регистров и плановых данных, хранящихся в спецификациях или документах. Одной из типичных трудностей является ошибка «нельзя использовать в запросе обращение к табличным частям» при попытке выполнить соединение. Разберем подробно, почему возникает эта проблема и как составить корректный запрос.

Причина возникновения ошибки обращения к вложенным таблицам

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

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

Решение проблемы через явное соединение таблиц

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

Рассмотрим пример правильного объединения данных регистра Запасы и табличной части Состав справочника Спецификации. Выясним причину успеха этого подхода: мы связываем записи напрямую по полям СчетУчета и Номенклатура.


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

В данном коде мы использовали псевдоним ТаблицаСпецификации для источника Справочник.Спецификации.Состав. Обратите внимание на условие связи: ТаблицаСпецификации.Ссылка.Владелец. Поскольку Ссылка в табличной части — это ссылка на сам справочник-хозяин, а у справочника Спецификации владельцем является Номенклатура, такая цепочка позволяет нам точно сопоставить записи регистра и нужной спецификации.

Оптимизация запроса с помощью временных таблиц

Хотя прямое соединение таблиц работает, в профессиональной разработке рекомендуется использовать временные таблицы. Это значительно повышает читаемость кода и производительность, так как СУБД проще обрабатывать несколько простых запросов, чем один перегруженный. Разберем этот метод по шагам.

Шаг 1. Подготовка данных регистра. Сначала выберем фактические данные из регистра во временную таблицу, сразу сгруппировав их.


ВЫБРАТЬ
    Запасы.КоррСчетУчета КАК КоррСчетУчета,
    Запасы.Номенклатура КАК Номенклатура,
    СУММА(Запасы.Сумма) КАК СуммаФакт
ПОМЕСТИТЬ ВТ_Факт
ИЗ
    РегистрНакопления.Запасы КАК Запасы
ГДЕ
    Запасы.Номенклатура = &Параметр
    И Запасы.Регистратор ССЫЛКА Документ.РаспределениеЗатрат
СГРУППИРОВАТЬ ПО
    Запасы.КоррСчетУчета,
    Запасы.Номенклатура
;

Шаг 2. Подготовка данных спецификации. Выберем плановые показатели из табличной части в другую временную таблицу.


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

Шаг 3. Финальное соединение. Теперь мы можем соединить две подготовленные легкие таблицы без риска получить ошибку вложенности.


ВЫБРАТЬ
    ЕСТЬNULL(ВТ_Факт.КоррСчетУчета, ВТ_План.СчетЗатрат) КАК СчетУчета,
    ВТ_Факт.СуммаФакт КАК Факт,
    ВТ_План.СуммаПлан КАК Себестоимость
ИЗ
    ВТ_Факт КАК ВТ_Факт
        ПОЛНОЕ СОЕДИНЕНИЕ ВТ_План КАК ВТ_План
        ПО ВТ_Факт.КоррСчетУчета = ВТ_План.СчетЗатрат
            И ВТ_Факт.Номенклатура = ВТ_План.НоменклатураВладелец

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

При работе с подобными отчетами в 1С следует учитывать несколько критически важных моментов, которые влияют на стабильность и скорость системы:

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

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

← На главную