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