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

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

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

Выясняем причину: почему табличная часть может быть пустой

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

Проанализируем механизмы хранения серий. В 1С:ERP заполнение ТЧ Серии напрямую зависит от настройки «Политики учета серий». Существует несколько вариантов поведения системы:

  1. Справочное указание серий: В этом режиме серии действительно записываются в табличную часть документа и служат лишь дополнительной информацией.
  2. Учет по остаткам: Если для склада или вида номенклатуры настроен полноценный учет остатков в разрезе серий, данные могут не дублироваться в табличных частях каждого документа для экономии места. Вместо этого система хранит связи в специализированных регистрах или скрытых системных таблицах.
  3. Статусы документов: Если документ находится в статусе «Черновик», данные могут присутствовать в ТЧ, но отсутствовать в регистрах. И наоборот — при определенных настройках интеграции серии могут появиться в движениях, но не попасть в ТЧ объекта.

Важный вывод: Для надежной проверки дублей всегда следует обращаться к регистру накопления ДвиженияСерийТоваров, так как именно он является «первоисточником» фактического движения серий в системе.

Оптимизация условий: избавляемся от громоздких ИЛИ

Посмотрим на пример кода из исходного сообщения. Использование множественных конструкций ИЛИ (OR) для проверки типов документов и значений перечислений — это плохая практика, которая затрудняет чтение кода и замедляет работу SQL-сервера. Разберем, как это можно улучшить.

Вместо перечисления:


ГДЕ (ДвиженияСерийТоваров.СкладскаяОперация = Значение(Перечисление.СкладскиеОперации.ПроизводствоПродукции)
ИЛИ ДвиженияСерийТоваров.СкладскаяОперация = Значение(Перечисление.СкладскиеОперации.ПриемкаОтПоставщика)
ИЛИ ...)

Следует использовать конструкцию В (...). Рассмотрим подробнее исправленный вариант:


ГДЕ ДвиженияСерийТоваров.СкладскаяОперация В (
    ЗНАЧЕНИЕ(Перечисление.СкладскиеОперации.ПроизводствоПродукции),
    ЗНАЧЕНИЕ(Перечисление.СкладскиеОперации.ПриемкаОтПоставщика),
    ЗНАЧЕНИЕ(Перечисление.СкладскиеОперации.ВводОстатков),
    ЗНАЧЕНИЕ(Перечисление.СкладскиеОперации.ПриемкаПродукцииИзПроизводства)
)

Такой подход позволяет платформе 1С сформировать более эффективный SQL-запрос IN (...), который оптимизатор базы данных обрабатывает значительно быстрее.

Работа с типами документов через ТИПЗНАЧЕНИЯ

Аналогичная проблема возникает при проверке типов ссылок через ССЫЛКА. Когда мы пишем Документ ССЫЛКА Документ.ПриобретениеТоваровУслуг, SQL-сервер зачастую вынужден выполнять LEFT JOIN ко всем таблицам документов, указанным в условии, что сильно нагружает систему. Проанализируем более изящный способ через ТИПЗНАЧЕНИЯ.

Рекомендуемый метод проверки группы типов:


ГДЕ ТИПЗНАЧЕНИЯ(ДвиженияСерийТоваров.Документ) В (
    ТИП(Документ.ЭтапПроизводства2_2),
    ТИП(Документ.ПроизводствоБезЗаказа),
    ТИП(Документ.ВводОстатковТоваров),
    ТИП(Документ.ОприходованиеИзлишковТоваров),
    ТИП(Документ.ПриобретениеТоваровУслуг)
)

Конструкция ТИПЗНАЧЕНИЯ в запросе обращается к внутреннему полю идентификатора типа (в терминах SQL это обычно _Description_TRef), что работает на порядок быстрее, чем проверка каждой таблицы через ССЫЛКА.

Как правильно искать дубли: использование временных таблиц

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

Рассмотрим правильный алгоритм решения задачи:

  1. Выгружаем данные из регистра во Временную Таблицу.
  2. Индексируем временную таблицу по полям Серия и Номенклатура.
  3. Соединяем временную таблицу с основной таблицей документа через ВНУТРЕННЕЕ СОЕДИНЕНИЕ.

Важный нюанс: Сама по себе Серия в 1С не уникальна. Условный серийный номер «10001» может быть у «Чайника» и у «Перфоратора». Чтобы найти настоящие дубли, всегда нужно связывать таблицы по паре Номенклатура + Серия.

Пример эффективного запроса для поиска дублей

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


// 1. Помещаем серии текущего объекта во временную таблицу
ВЫБРАТЬ
    ТЧ.Номенклатура КАК Номенклатура,
    ТЧ.Серия КАК Серия
ПОМЕСТИТЬ ВТ_СерииОбъекта
ИЗ
    Документ.ПриобретениеТоваровУслуг.Товары КАК ТЧ // Или работаем через ДвиженияСерийТоваров
ГДЕ
    ТЧ.Ссылка = &ТекущийОбъект
ИНДЕКСИРОВАТЬ ПО
    Номенклатура,
    Серия
;

// 2. Ищем пересечения с регистром
ВЫБРАТЬ
    Регистр.Документ КАК ДокументДубль,
    ВТ.Серия КАК Серия,
    ВТ.Номенклатура КАК Номенклатура
ИЗ
    ВТ_СерииОбъекта КАК ВТ
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.ДвиженияСерийТоваров КАК Регистр
        ПО ВТ.Номенклатура = Регистр.Номенклатура
            И ВТ.Серия = Регистр.Серия
ГДЕ
    Регистр.Документ <> &ТекущийОбъект
    И ТИПЗНАЧЕНИЯ(Регистр.Документ) В (ТИП(Документ.ПриобретениеТоваровУслуг), ТИП(Документ.ЭтапПроизводства2_2))

Использование ВНУТРЕННЕЕ СОЕДИНЕНИЕ вместо В (ВЫБРАТЬ...) гарантирует, что SQL-сервер применит оптимальный план выполнения запроса. А индексация временной таблицы сделает поиск мгновенным даже при миллионах записей в регистре.

Заключение

Подведем итог. Если ваш запрос «не видит» данные, проверьте, в том ли месте вы их ищете (ТЧ против Регистра). При написании условий откажитесь от бесконечных ИЛИ в пользу оператора В и используйте ТИПЗНАЧЕНИЯ. Эти простые правила не только решат проблему пустых результатов, но и сделают ваш код профессиональным и быстродействующим.

← На главную