Как выбрать документы реализации, содержащие весь список указанной номенклатуры?

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

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

Постановка задачи и подходы

Для начала важно понять, что именно мы ищем. В зависимости от требований бизнеса возможны два сценария:

  1. Документ содержит все товары из списка, но может содержать и что-то еще. Это наиболее частая задача.
  2. Документ содержит строго только тот перечень товаров, который передан в параметре, и ничего лишнего.

В обоих случаях нам не нужно перебирать документы в цикле, что было бы крайне непроизводительно. Мы воспользуемся мощью Запрос и операторами СГРУППИРОВАТЬ ПО и ИМЕЮЩИЕ.

Решение через подсчет количества номенклатур

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

Реализуем это решение по шагам:

  1. Определяем количество номенклатур во входящем списке.
  2. Выбираем из табличной части Товары только те записи, которые входят в наш список.
  3. Группируем результат по ссылке на документ и считаем количество уникальных номенклатур.
  4. Фильтруем результат с помощью условия ИМЕЮЩИЕ, чтобы оставить только те документы, где количество совпадений равно количеству позиций в исходном списке.

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


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

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

ВЫБРАТЬ
    Соответствия.Реализация
ИЗ
    ВТ_Соответствия КАК Соответствия
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_КоличествоСписка КАК ОбщееКоличество
    ПО Соответствия.КолВоВДокументе = ОбщееКоличество.КолВоВсего

Почему этот метод эффективен?

Использование КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...) позволяет исключить дубли, если товар в документе добавлен в табличную часть несколько раз (например, разными строками). Сравнение с количеством элементов во входящем списке является математически точным способом проверки полноты набора данных в документе.

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

Альтернативный взгляд: проверка отсутствия

Если вам нужно убедиться, что документ не содержит ничего «лишнего» (то есть состоит только из переданных товаров), вы можете добавить условие сравнения общего количества строк в документе с количеством строк, входящих в список.

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

Теперь, когда мы разобрали основные шаги, вы можете легко адаптировать этот код под свои нужды, добавив необходимые фильтры по дате или контрагенту. Успехов в разработке!

← На главную