Почему в отчете 1С выводится несколько разных цен для одной номенклатуры и как это исправить?

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

Часто начинающие разработчики 1С сталкиваются с ситуацией, когда при создании отчета по остаткам и ценам одна и та же номенклатура выводится несколькими строками с разными ценами, даже если выбран один конкретный тип цен (например, «Оптовая»). Это создает путаницу и делает отчет некорректным. Разберем детально причины возникновения этой проблемы и способы её решения на примере конфигурации «Управление торговлей».

Проблема: возникновение дублей в запросе

Рассмотрим типичную ситуацию. В запросе соединяются две таблицы: остатки товаров на складах и актуальные цены. На первый взгляд запрос выглядит логично, но в результате мы видим картину, когда для одного товара на одном складе выводится три строки с ценами 190, 220 и 170 рублей. При этом остаток в каждой строке дублируется.

Проанализируем исходный код запроса, который часто становится причиной такой ошибки:


ВЫБРАТЬ РАЗЛИЧНЫЕ
    ТоварыНаСкладахОстатки.Склад.Ссылка КАК Склад,
    ТоварыНаСкладахОстатки.Номенклатура.НаименованиеПолное КАК Наименование,
    ЦеныНоменклатурыСрезПоследних.Цена,
    ТоварыНаСкладахОстатки.КоличествоОстаток КАК Остаток
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки КАК ТоварыНаСкладахОстатки
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК ЦеныНоменклатурыСрезПоследних
        ПО ТоварыНаСкладахОстатки.Номенклатура.Ссылка = ЦеныНоменклатурыСрезПоследних.Номенклатура.Ссылка
ГДЕ
    ЦеныНоменклатурыСрезПоследних.ТипЦен.Ссылка = &Ссылка

Причина №1: Использование характеристик номенклатуры

Главная причина, по которой возникают подобные дубли, — это наличие в системе характеризок номенклатуры (цвет, размер, модель). Если в настройках программы включен учет по характеристикам, то цена в регистре ЦеныНоменклатуры устанавливается не просто на товар, а на связку «Номенклатура + Характеристика».

В приведенном выше запросе соединение (JOIN) происходит только по полю Номенклатура. Это означает, что если для одного товара создано три разные характеристики и для каждой установлена своя цена, запрос подтянет все три записи из регистра цен к одной записи остатка. Система «не понимает», какую именно цену выбрать, и выводит все доступные варианты.

Решение: необходимо обязательно добавлять характеристику в условия соединения таблиц. Если мы выводим остатки, то и цена должна соответствовать конкретной характеристике товара на складе.


ПО ТоварыНаСкладахОстатки.Номенклатура = ЦеныНоменклатурыСрезПоследних.Номенклатура
    И ТоварыНаСкладахОстатки.Характеристика = ЦеныНоменклатурыСрезПоследних.Характеристика

Причина №2: Неправильное использование параметров виртуальных таблиц

Посмотрим на блок ГДЕ в исходном запросе. Фильтрация по типу цен происходит после того, как таблицы были соединены. Это не только замедляет работу отчета, но и может приводить к логическим ошибкам при работе со срезом последних данных.

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

Правильный вариант обращения к таблице цен:


РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ТипЦен = &ВыбранныйТипЦен) КАК ЦеныНоменклатурыСрезПоследних

Причина №3: Избыточные обращения через точку (.Ссылка)

В коде новичков часто встречается конструкция Склад.Ссылка или ТипЦен.Ссылка. Это важный технический момент. Поля Склад, Номенклатура, ТипЦен в регистрах уже являются ссылочными типами. Когда вы добавляете .Ссылка, 1С выполняет дополнительную операцию в базе данных (обращение к таблице справочника), чтобы получить значение, которое и так доступно в исходной таблице. Это снижает производительность и загромождает код.

Рекомендация: всегда пишите просто ТоварыНаСкладахОстатки.Склад вместо ТоварыНаСкладахОстатки.Склад.Ссылка.

Причина №4: Вид соединения таблиц

Использование ВНУТРЕННЕЕ СОЕДИНЕНИЕ (INNER JOIN) приводит к тому, что если у товара есть остаток, но на него еще не установлена цена, этот товар вообще исчезнет из отчета. В управленческих отчетах это критично — менеджер не увидит товар в наличии.

Решение: используйте ЛЕВОЕ СОЕДИНЕНИЕ. В этом случае в отчет попадут все товары, имеющиеся на остатках, а в колонке «Цена» будет пустое значение (NULL), если цена не задана. Чтобы вместо пустоты выводить ноль, можно использовать функцию ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0).

Итоговый корректный запрос

С учетом всех разобранных ошибок, составим оптимальный и правильный запрос для получения отчета без дублей:


ВЫБРАТЬ
    ТоварыНаСкладахОстатки.Склад КАК Склад,
    ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура,
    ТоварыНаСкладахОстатки.Характеристика КАК Характеристика,
    ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0) КАК Цена,
    ЦеныНоменклатурыСрезПоследних.ТипЦен КАК ТипЦены,
    ТоварыНаСкладахОстатки.КоличествоОстаток КАК Остаток
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК ТоварыНаСкладахОстатки
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ТипЦен = &ТипЦен) КАК ЦеныНоменклатурыСрезПоследних
        ПО ТоварыНаСкладахОстатки.Номенклатура = ЦеныНоменклатурыСрезПоследних.Номенклатура
            И ТоварыНаСкладахОстатки.Характеристика = ЦеныНоменклатурыСрезПоследних.Характеристика

Дополнительные факторы, о которых стоит помнить

  1. Валюты: Если в одном типе цен цены могут задаваться в разных валютах (рубли, доллары), в регистре появится измерение Валюта. Если его не учесть в соединении или фильтре, дубли вернутся.
  2. Упаковки: В современных версиях УТ цена может зависеть от единицы измерения (упаковки). Если одна цена за штуку, а другая за коробку, запрос без учета упаковок также выдаст две строки.
  3. Расчетные цены: Если выбранный тип цен является динамическим (рассчитывается как «Закупка + %»), то в физической таблице цен записей может не быть вовсе. В таком случае СрезПоследних не поможет, и потребуется использовать механизмы программного расчета цен или СКД (Систему компоновки данных).

Подведем итог. Чтобы избавиться от «лишних» цен в отчете, всегда проверяйте, по всем ли ключевым измерениям регистра сведений (Номенклатура, Характеристика, ТипЦен, Валюта) выполнено соединение и установлены ли фильтры в параметрах виртуальных таблиц. Это обеспечит точность данных и высокую скорость формирования отчета.

← На главную