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

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

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

Анализ проблемы: почему не подходит внутреннее соединение

В исходном варианте запроса часто используется ВНУТРЕННЕЕ СОЕДИНЕНИЕ (Inner Join). Это критическая ошибка для данной задачи. Внутреннее соединение возвращает только те записи, которые есть в обоих источниках. Если в документе появилась новая номенклатура, которой еще нет в регистре сведений, запрос её просто проигнорирует. Кроме того, прямое сравнение цен без учета пустых значений (NULL) также отсеивает новые записи.

Для корректного решения нам необходимо выполнить несколько последовательных шагов в рамках пакетного запроса.

Шаг 1. Подготовка данных документа

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

Также для повышения производительности создадим индексы по полям связи — Номенклатура и Цвет.


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

Шаг 2. Получение текущих цен из регистра

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


ВЫБРАТЬ
    РСЦеныНоменклатурыСрезПоследних.Номенклатура КАК Номенклатура,
    РСЦеныНоменклатурыСрезПоследних.Цвет КАК Цвет,
    РСЦеныНоменклатурыСрезПоследних.Цена КАК Цена
ПОМЕСТИТЬ ВТ_РСНоменклатура
ИЗ
    РегистрСведений.РСЦеныНоменклатуры.СрезПоследних(
        &Период,
        Номенклатура В (ВЫБРАТЬ ВТ.Номенклатура ИЗ ВТ_НоменклатураДокумента КАК ВТ)) КАК РСЦеныНоменклатурыСрезПоследних
ИНДЕКСИРОВАТЬ ПО
    Номенклатура,
    Цвет
;

Шаг 3. Соединение таблиц и фильтрация результатов

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

Проанализируем условие в секции ГДЕ. Нам нужны строки, в которых:

  1. Цена в документе не совпадает с ценой в регистре.
  2. ИЛИ запись в регистре отсутствует вовсе (новая номенклатура).

Для корректной обработки NULL используем функцию ЕСТЬNULL. Посмотрим на итоговый запрос:


ВЫБРАТЬ
    ВТ_Док.Номенклатура,
    ВТ_Док.Цвет,
    ВТ_Док.Цена КАК ЦенаНовая,
    ЕСТЬNULL(ВТ_РС.Цена, 0) КАК ЦенаСтарая
ИЗ
    ВТ_НоменклатураДокумента КАК ВТ_Док
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_РСНоменклатура КАК ВТ_РС
        ПО ВТ_Док.Номенклатура = ВТ_РС.Номенклатура
            И ВТ_Док.Цвет = ВТ_РС.Цвет
ГДЕ
    ВТ_Док.Цена <> ЕСТЬNULL(ВТ_РС.Цена, -1)

Обратите внимание: в функции ЕСТЬNULL(ВТ_РС.Цена, -1) мы подставляем значение -1 (или любое другое заведомо невозможное для цены значение), чтобы при отсутствии записи в регистре условие Цена <> -1 гарантированно сработало для новой номенклатуры.

Важные технические нюансы

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

Таким образом, использование временных таблиц в сочетании с левым соединением и функцией ЕСТЬNULL позволяет эффективно решать задачу сравнения данных и выявления изменений в учетных системах 1С.

← На главную