При разработке отчетов в 1С:Управление торговлей 11.4 часто возникает ситуация, когда в итоговой таблице начинают дублироваться строки номенклатуры или подтягиваются странные единицы измерения, которые не соответствуют действительности. Особенно это актуально для сложных запросов, где соединяются документы перемещения, поступления и регистры цен. Разберем по шагам, почему это происходит и как правильно сконструировать запрос, чтобы получить корректные данные.
Рассмотрим исходную ситуацию: разработчик пытается выгрузить данные о перемещении товаров, соединяя основную таблицу документа Документ.ПеремещениеТоваров с его же табличной частью через ЛЕВОЕ СОЕДИНЕНИЕ. При этом внутри самого списка полей используется обращение к вложенной таблице через точку: ПеремещениеТоваров.Товары.(...).
Проанализируем, почему такая конструкция ошибочна. В системе 1С при использовании конструкции выбора вложенной таблицы в плоском запросе происходит конфликт механизмов выборки. Если мы одновременно делаем соединение с табличной частью и просим систему выдать эту же табличную часть как вложенную таблицу в одной строке, платформа может продублировать записи для каждой строки из соединения. Выясним причину появления разных единиц измерения: в конфигурациях на базе ERP-платформы (УТ 11, КА 2, ERP) у номенклатуры есть Единица хранения и могут быть Упаковки. Если в запросе обращаться к Номенклатура.ЕдиницаИзмерения, мы всегда будем получать базовую единицу, но в регистре цен или в табличной части документа могут быть зафиксированы упаковки (например, «метры» вместо «штук»), что и создает иллюзию задвоения с разными единицами.
Вместо того чтобы начинать запрос от «шапки» документа (ссылки), мы должны строить его от основной аналитической единицы — строки табличной части. Это позволит нам получить плоскую таблицу без лишних вложенных циклов. Посмотрим на пример правильной структуры запроса:
ВЫБРАТЬ
ПеремещениеТовары.Ссылка КАК ДокументПеремещения,
ПеремещениеТовары.Номенклатура КАК Номенклатура,
ПеремещениеТовары.Номенклатура.ЕдиницаИзмерения КАК ЕдИзмБазовая,
ПеремещениеТовары.Упаковка КАК ЕдИзмДокумента,
ПеремещениеТовары.Количество КАК Количество,
ПеремещениеТовары.Ссылка.СкладПолучатель КАК СкладПолучатель,
ПеремещениеТовары.Ссылка.ДокументОснование КАК Поступление,
Цены.Цена КАК ЦенаЗакупки
ИЗ
Документ.ПеремещениеТоваров.Товары КАК ПеремещениеТовары
Обратим внимание на важный момент: обращаясь напрямую к Документ.ПеремещениеТоваров.Товары, мы получаем доступ ко всем реквизитам «шапки» через поле Ссылка. Это исключает необходимость в лишних соединениях (JOIN) между документом и его табличной частью, что положительно сказывается на производительности и исключает логические ошибки дублирования строк.
Часто в подобных отчетах требуется получить цену на момент совершения операции. В исходном примере использовалась виртуальная таблица СрезПервых. Однако для управленческих отчетов чаще требуется именно актуальная цена на дату документа, что обеспечивается таблицей СрезПоследних.
Разберем типичные ошибки при соединении с регистром цен:
ВидЦены в параметрах виртуальной таблицы или в условии соединения, запрос выдаст столько строк по одной позиции номенклатуры, сколько видов цен для нее задано. Это одна из главных причин «задвоения».СрезПоследних и передаем в параметры дату документа.Рассмотрим, как правильно настроить соединение с ценами:
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ВидЦены = &НужныйВидЦены) КАК Цены
ПО ПеремещениеТовары.Номенклатура = Цены.Номенклатура
В процессе анализа кода мы можем встретить обращение типа Цены.Регистратор.Дата. Проанализируем ситуацию: поле Регистратор в регистрах сведений является составным типом (оно может ссылаться на десятки видов документов). Когда мы пишем .Дата, платформа 1С на уровне SQL-запроса выполняет LEFT JOIN со всеми таблицами документов, которые могут быть регистраторами для этого регистра. Это катастрофически замедляет выполнение отчета.
Для оптимизации рекомендуется использовать поле Период самого регистра, которое в 99% случаев совпадает с датой регистратора, но уже проиндексировано и доступно без обращений к другим таблицам. Если же вам критически нужна дата именно документа-регистратора, лучше сначала выбрать данные во временную таблицу, а затем соединить её с конкретной таблицей нужного типа документа.
Для того чтобы отчет по перемещениям работал корректно и быстро, придерживаемся следующих правил:
Документ.ПеремещениеТоваров.Товары. Выкидываем все конструкции вида ПеремещениеТоваров.Товары.(...) из текста запроса.Упаковка. Если нужна базовая единица товара — Номенклатура.ЕдиницаИзмерения. Никогда не смешиваем их в одном поле без приведения к общему коэффициенту (через поле Коэффициент).ЦеныНоменклатуры обязательно накладываем условие на ВидЦены. Это предотвратит размножение строк.Документ.ПеремещениеТоваров с его ТЧ вручную, если в этом нет специфической необходимости. Доступ к реквизитам документа через Товары.Ссылка.Дата работает эффективнее и надежнее.Соблюдение этих архитектурных правил позволит вам создавать чистые, быстрые и, самое главное, достоверные отчеты в системе 1С:Предприятие.