При разработке отчетов или обработок в 1С:Управление торговлей 11.4 часто возникает задача поиска документов, табличные части которых содержат не просто одну из позиций списка, а весь переданный набор товаров целиком. В реляционной алгебре эта задача называется реляционным делением. Давайте разберем, как эффективно решить эту проблему средствами встроенного языка запросов 1С.
Для начала важно понять, что именно мы ищем. В зависимости от требований бизнеса возможны два сценария:
В обоих случаях нам не нужно перебирать документы в цикле, что было бы крайне непроизводительно. Мы воспользуемся мощью Запрос и операторами СГРУППИРОВАТЬ ПО и ИМЕЮЩИЕ.
Рассмотрим самый оптимальный метод, который позволяет найти все документы, содержащие нужный перечень товаров. Суть решения заключается в следующем: мы считаем, сколько уникальных позиций из нашего списка встречается в каждом документе, и сравниваем это число с общим количеством элементов в исходном списке.
Реализуем это решение по шагам:
Товары только те записи, которые входят в наш список.ИМЕЮЩИЕ, чтобы оставить только те документы, где количество совпадений равно количеству позиций в исходном списке.Посмотрим на пример реализации такого кода:
ВЫБРАТЬ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Спр.Ссылка) КАК КолВоВсего
ПОМЕСТИТЬ ВТ_КоличествоСписка
ИЗ
Справочник.Номенклатура КАК Спр
ГДЕ
Спр.Ссылка В(&СписокНоменклатуры)
;
ВЫБРАТЬ
Товары.Ссылка КАК Реализация,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Товары.Номенклатура) КАК КолВоВДокументе
ПОМЕСТИТЬ ВТ_Соответствия
ИЗ
Документ.РеализацияТоваровИУслуг.Товары КАК Товары
ГДЕ
Товары.Номенклатура В(&СписокНоменклатуры)
СГРУППИРОВАТЬ ПО
Товары.Ссылка
;
ВЫБРАТЬ
Соответствия.Реализация
ИЗ
ВТ_Соответствия КАК Соответствия
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_КоличествоСписка КАК ОбщееКоличество
ПО Соответствия.КолВоВДокументе = ОбщееКоличество.КолВоВсего
Использование КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...) позволяет исключить дубли, если товар в документе добавлен в табличную часть несколько раз (например, разными строками). Сравнение с количеством элементов во входящем списке является математически точным способом проверки полноты набора данных в документе.
Важные рекомендации по оптимизации:
INNER JOIN), что значительно быстрее, чем использование оператора В с большим массивом данных.1С — ресурсоемкая операция.Номенклатура в табличной части Товары проиндексировано. В стандартных конфигурациях УТ 11 индексы обычно присутствуют, но в доработанных системах это стоит проверить.Если вам нужно убедиться, что документ не содержит ничего «лишнего» (то есть состоит только из переданных товаров), вы можете добавить условие сравнения общего количества строк в документе с количеством строк, входящих в список.
Анализируя ситуацию, важно понимать, что при использовании метода «двойного отрицания» (поиск того, чего нет) мы можем найти те реализации, где отсутствуют критически важные позиции. Этот подход требует больше ресурсов, так как он оперирует полным декартовым произведением, поэтому метод с подсчетом количества через СГРУППИРОВАТЬ является предпочтительным для большинства задач в 1С.
Теперь, когда мы разобрали основные шаги, вы можете легко адаптировать этот код под свои нужды, добавив необходимые фильтры по дате или контрагенту. Успехов в разработке!