Почему пропадают данные при соединении временных таблиц в запросе 1С и как это исправить?

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

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

Анализ проблемы: почему ЛЕВОЕ СОЕДИНЕНИЕ может «терять» данные

Рассмотрим типичную ситуацию. У нас есть две временные таблицы: втКлиенты (данные по заказам) и ВТПроизводство (данные по выпуску продукции). Мы пытаемся связать их по полям ЗаказКлиента и Номенклатура, используя ЛЕВОЕ СОЕДИНЕНИЕ. Если мы ожидаем увидеть все заказы и привязанные к ним выпуски, но часть строк исчезает, причина обычно кроется в одном из следующих аспектов:

  1. Несоответствие ключей связи. Если в одной таблице поле имеет тип конкретной ссылки, а в другой — составной тип (или NULL), соединение не сработает.
  2. Лишние поля в условии связи. Использование таких полей как КодСтроки часто приводит к тому, что записи не сопоставляются, если в одном из документов этот код заполнен иначе.
  3. Фильтрация в блоке ГДЕ. Если после левого соединения наложить условие на поле из правой (присоединяемой) таблицы без проверки на NULL, вся строка будет отсечена, если данных во второй таблице не нашлось.

Решение №1: Использование ПОЛНОГО СОЕДИНЕНИЯ

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

Рассмотрим пример правильного подхода с проверкой на NULL:


ВЫБРАТЬ
    ЕСТЬNULL(втКлиенты.ЗаказКлиента, ВТПроизводство.ЗаказКлиента) КАК ЗаказКлиента,
    ЕСТЬNULL(втКлиенты.Номенклатура, ВТПроизводство.Номенклатура) КАК Номенклатура,
    ЕСТЬNULL(втКлиенты.Заказано, 0) КАК Заказано,
    ЕСТЬNULL(ВТПроизводство.ПланКолво, 0) КАК ПланКолво
ИЗ
    втКлиенты КАК втКлиенты
        ПОЛНОЕ СОЕДИНЕНИЕ ВТПроизводство КАК ВТПроизводство
        ПО втКлиенты.ЗаказКлиента = ВТПроизводство.ЗаказКлиента
            И втКлиенты.Номенклатура = ВТПроизводство.Номенклатура

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

Решение №2: Использование конструкции ОБЪЕДИНИТЬ ВСЕ и группировки

В среде 1С профессиональным стандартом для объединения данных из нескольких источников считается метод «Объединить все + Группировка». Этот способ часто работает быстрее полного соединения и позволяет избежать сложных условий связи.

Проанализируем шаги реализации этого метода:

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

Пример реализации:


ВЫБРАТЬ
    Т.ЗаказКлиента,
    Т.Номенклатура,
    СУММА(Т.Заказано) КАК Заказано,
    СУММА(Т.ПланКолво) КАК ПланКолво
ИЗ
    (ВЫБРАТЬ
        втКлиенты.ЗаказКлиента КАК ЗаказКлиента,
        втКлиенты.Номенклатура КАК Номенклатура,
        втКлиенты.Заказано КАК Заказано,
        0 КАК ПланКолво
    ИЗ
        втКлиенты КАК втКлиенты
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        ВТПроизводство.ЗаказКлиента,
        ВТПроизводство.Номенклатура,
        0,
        ВТПроизводство.ПланКолво
    ИЗ
        ВТПроизводство КАК ВТПроизводство) КАК Т

СГРУППИРОВАТЬ ПО
    Т.ЗаказКлиента,
    Т.Номенклатура

Этот метод гарантирует, что ни одна запись не будет потеряна из-за отсутствия пары в другой таблице или из-за проблем с NULL в условиях связи.

Технические тонкости, о которых важно помнить

Проанализируем дополнительные факторы, которые могут влиять на результат запроса:

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

2. Проблема «Кода строки». В типовых конфигурациях (ERP, УТ 11) поле КодСтроки используется для разделения одинаковой номенклатуры в одном документе. Если вы соединяете таблицы по этому полю, убедитесь, что оно заполнено в обоих источниках. Часто в регистрах оборотов КодСтроки может быть равен 0, в то время как в документе он заполнен. В таких случаях соединение по этому полю лучше исключить, предварительно сгруппировав данные по номенклатуре.

3. Неявное приведение типов. Если в одной таблице ЗаказКлиента получен из объектной таблицы (Документ.ЗаказКлиента), а в другой через обращение к реквизиту другого документа (например, ЗаказНаПроизводство.ДокументОснование), типы могут не совпасть, если основание имеет составной тип. Попробуйте явно привести типы с помощью ВЫРАЗИТЬ(Поле КАК Документ.ЗаказКлиента).

4. Работа с виртуальными таблицами. При использовании таблицы Обороты старайтесь накладывать условия не в секции ГДЕ, а в параметрах самой виртуальной таблицы. Это работает стабильнее и быстрее. Например:


ИЗ РегистрНакопления.ЗаказыКлиентов.Обороты(&НачалоПериода, &КонецПериода, Авто, ЗаказКлиента В (&МассивЗаказов)) КАК Заказы

Разберем итог: если данные пропадают при соединении, первым делом проверьте типы связующих полей. Если логика задачи подразумевает наличие данных хотя бы в одном из источников — используйте ОБЪЕДИНИТЬ ВСЕ с последующей группировкой. Это самый надежный способ избежать «магического» исчезновения строк в отчетах.

← На главную