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

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

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

Причина ошибки «Содержимое объекта данных может быть выбрано только во временную таблицу»

При попытке напрямую обратиться к переданной в запрос таблице значений (через параметр &Таблица1), разработчики часто сталкиваются с ошибкой: «Содержимое объекта данных может быть выбрано только во временную таблицу». Проанализируем ситуацию: это происходит потому, что платформа 1С не может выполнять сложные операции (такие как соединения или объединения) непосредственно с объектом в оперативной памяти (таблицей значений), который еще не «физически» находится в базе данных SQL.

Для решения этой проблемы мы должны сначала поместить данные во временные таблицы. Рассмотрим, как это сделать правильно:


ВЫБРАТЬ
    Таблица1.Номенклатура КАК Номенклатура,
    Таблица1.Характеристика КАК Характеристика,
    Таблица1.Количество КАК Количество
ПОМЕСТИТЬ ВТ_Таблица1
ИЗ
    &Таблица1 КАК Таблица1
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Таблица2.Номенклатура КАК Номенклатура,
    Таблица2.Характеристика КАК Характеристика,
    Таблица2.Количество КАК Количество
ПОМЕСТИТЬ ВТ_Таблица2
ИЗ
    &Таблица2 КАК Таблица2
;

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

Метод 1: Использование соединений (ЛЕВОЕ и ПОЛНОЕ)

Рассмотрим первый способ, который часто приходит на ум — использование ЛЕВОЕ СОЕДИНЕНИЕ. Чтобы найти строки, которые есть в первой таблице, но отсутствуют во второй, мы проверяем вторую таблицу на NULL.

Однако, чтобы найти все различия, нам пришлось бы объединять три разных запроса:

  1. Те, что есть в Т1, но нет в Т2 (Левое соединение + ГДЕ Т2.Ключ ЕСТЬ NULL).
  2. Те, что есть в Т2, но нет в Т1 (Правое соединение + ГДЕ Т1.Ключ ЕСТЬ NULL).
  3. Те, что есть в обеих, но отличаются по количеству.

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

Метод 2: Эффективное сравнение через ОБЪЕДИНИТЬ ВСЕ и группировку

Проанализируем более изящный и производительный метод, который часто называют «методом весовых коэффициентов» или «симметрической разностью». Идея заключается в том, чтобы объединить данные двух таблиц в один список, при этом количество из первой таблицы взять со знаком «плюс», а из второй — со знаком «минус».

Разберем по шагам, как работает этот алгоритм:

  1. Выбираем данные из ВТ_Таблица1, количество оставляем как есть.
  2. Используем ОБЪЕДИНИТЬ ВСЕ и выбираем данные из ВТ_Таблица2, умножая количество на -1.
  3. Группируем полученный результат по ключевым полям (Номенклатура, Характеристика).
  4. Суммируем количество. Если итоговая сумма равна нулю, значит, строки в обеих таблицах были идентичны, и они «схлопнулись». Если сумма не равна нулю — перед нами различие.

Посмотрим на пример реализации такого запроса:


ВЫБРАТЬ
    ПолныеДанные.Номенклатура КАК Номенклатура,
    ПолныеДанные.Характеристика КАК Характеристика,
    СУММА(ПолныеДанные.Количество) КАК РазницаКоличество
ИЗ
    (ВЫБРАТЬ
        Т1.Номенклатура КАК Номенклатура,
        Т1.Характеристика КАК Характеристика,
        Т1.Количество КАК Количество
    ИЗ
        ВТ_Таблица1 КАК Т1
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        Т2.Номенклатура,
        Т2.Характеристика,
        -Т2.Количество
    ИЗ
        ВТ_Таблица2 КАК Т2) КАК ПолныеДанные

СГРУППИРОВАТЬ ПО
    ПолныеДанные.Номенклатура,
    ПолныеДанные.Характеристика

ИМЕЮЩИЕ
    СУММА(ПолныеДанные.Количество) <> 0

Почему этот метод лучше?

Во-первых, мы получаем все виды расхождений одним списком:

Во-вторых, этот метод устойчив к дублям в исходных таблицах. Если в ВТ_Таблица1 номенклатура «Болт» встречается двумя строками по 5 штук, а в ВТ_Таблица2 — одной строкой 10 штук, группировка корректно покажет нулевую разницу.

Тонкости типизации и пустых значений

При сравнении таблиц в 1С важно помнить о типах данных. Выясним причину возможных сбоев: если колонки вашей ТаблицыЗначений не имеют жестко заданного типа (тип «Произвольный»), запрос может отработать некорректно или выдать ошибку при сравнении ссылочных типов.

Рекомендации при подготовке данных:

  1. Всегда создавайте ТаблицуЗначений с описанием типов колонок: Новый ОписаниеТипов("СправочникСсылка.Номенклатура").
  2. При помещении во временную таблицу используйте функцию ЕСТЬNULL(Т1.Количество, 0), чтобы избежать ошибок арифметических операций с неопределенными значениями.
  3. Если вы сравниваете не только количество, но и, например, цену, логика остается той же: используйте разность и условие ИМЕЮЩИЕ.

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

← На главную