При разработке отчетов в конфигурации «1С:Управление торговлей 10.3» начинающие программисты часто сталкиваются с проблемой «размножения» строк в результате выполнения запроса. Особенно остро это проявляется при попытке объединить данные о номенклатуре, её остатках, ценах и штрихкодах. В этой статье мы подробно разберем, почему возникают дубли, как правильно связывать таблицы и как оптимизировать запрос для получения корректного результата.
Рассмотрим ситуацию, когда нам необходимо получить список товаров, их розничную цену, текущий остаток на складах и штрихкод. Основная сложность заключается в том, что данные хранятся в разных объектах: справочнике Номенклатура, регистре накопления ТоварыНаСкладах и регистрах сведений ЦеныНоменклатуры и Штрихкоды.
Проанализируем основные причины возникновения ошибок и дублей, упомянутые в обсуждении:
Штрихкоды нет измерения Номенклатура. Вместо него используется измерение Владелец, которое имеет составной тип данных (обычно это ссылка на справочник Номенклатура). Использование несуществующего поля приводит к ошибке выполнения.СрезПоследних без указания параметров (например, без фильтра по типу цен), система сначала выберет все цены для всех типов (оптовые, розничные, закупочные), и только потом применит фильтр ГДЕ. Это не только замедляет работу, но и часто становится причиной некорректного соединения данных.Выясним причину, по которой цены могут задваиваться или выводиться неверно. В УТ 10.3 цены хранятся в разрезе типов цен. Чтобы получить только розничные цены, мы должны передать этот параметр непосредственно в виртуальную таблицу. Посмотрим на пример правильного обращения:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Товар,
ЦеныНоменклатурыСрезПоследних.Цена КАК Цена
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ТипЦен = &ТипЦен) КАК ЦеныНоменклатурыСрезПоследних
ПО ЦеныНоменклатурыСрезПоследних.Номенклатура = Номенклатура.Ссылка
Использование ЛЕВОЕ СОЕДИНЕНИЕ гарантирует, что в список попадут все товары из справочника, даже если для них еще не установлена цена. Если использовать внутреннее соединение, товары без цен просто исчезнут из результата.
Рассмотрим подробнее, как добавить остатки. Если нам нужен общий остаток по всем складам, мы используем виртуальную таблицу Остатки регистра ТоварыНаСкладах. Важно помнить: если мы не укажем склад в параметрах таблицы, но добавим его в поле ВЫБРАТЬ, номенклатура продублируется столько раз, на скольких складах она числится.
Проанализируем ситуацию с остатками в коде:
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК ТоварыНаСкладахОстатки
ПО ТоварыНаСкладахОстатки.Номенклатура = Номенклатура.Ссылка
В секции ВЫБРАТЬ следует использовать функцию ЕСТЬNULL(ТоварыНаСкладахОстатки.КоличествоОстаток, 0), чтобы вместо пустых значений (NULL) для товаров без остатка выводился красивый ноль.
Теперь разберем самую сложную часть — вывод штрихкода без дублей. Как уже было сказано, штрихкод в УТ 10.3 привязан к владельцу, единице измерения и характеристике. Чтобы гарантированно получить одну строку, мы применим два метода:
Владелец вместо Номенклатура.Посмотрим на пример реализации этого условия в соединении:
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Штрихкоды КАК Штрихкоды
ПО Штрихкоды.Владелец = Номенклатура.Ссылка
И Штрихкоды.ЕдиницаИзмерения = Номенклатура.ЕдиницаХраненияОстатков
И Штрихкоды.ХарактеристикаНоменклатуры = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)
Если же ваша задача — вывести вообще любой штрихкод, который есть у товара (если их несколько), лучше использовать вложенный запрос с группировкой по полю Владелец и функцией МАКСИМУМ(Штрихкод).
Соберем все наши наработки в единый работающий код. Мы исправим синтаксические ошибки, выявленные в ходе обсуждения (такие как лишние запятые перед соединениями), и приведем запрос к профессиональному виду:
ВЫБРАТЬ
СправочникНоменклатура.Наименование КАК Наименование,
СправочникНоменклатура.Артикул КАК Артикул,
ЕСТЬNULL(ЦеныНоменклатуры.Цена, 0) КАК Цена,
ЕСТЬNULL(ТоварыНаСкладах.КоличествоОстаток, 0) КАК Остаток,
ЕСТЬNULL(Штрихкоды.Штрихкод, "---") КАК Штрихкод
ИЗ
Справочник.Номенклатура КАК СправочникНоменклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ТипЦен = &ТипЦен) КАК ЦеныНоменклатуры
ПО СправочникНоменклатура.Ссылка = ЦеныНоменклатуры.Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК ТоварыНаСкладах
ПО СправочникНоменклатура.Ссылка = ТоварыНаСкладах.Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Штрихкоды КАК Штрихкоды
ПО СправочникНоменклатура.Ссылка = Штрихкоды.Владелец
И СправочникНоменклатура.ЕдиницаХраненияОстатков = Штрихкоды.ЕдиницаИзмерения
ГДЕ
НЕ СправочникНоменклатура.ЭтоГруппа
Проанализируем структуру этого решения:
Номенклатура. Это позволяет нам видеть весь ассортимент. Условие НЕ СправочникНоменклатура.ЭтоГруппа отсекает папки, оставляя только позиции товаров.&Период и &ТипЦен в СрезПоследних. Это критически важно для производительности в больших базах данных.ЕдиницаХраненияОстатков отсекает дубли, которые возникают, когда у товара есть штрихкоды на разные упаковки.Таким образом, мы рассмотрели пошаговое создание чистого и эффективного запроса для «1С:Управление торговлей 10.3». Следуя этим правилам, вы сможете избежать «раздувания» отчетов и предоставлять руководству только достоверные данные.