Как в запросе 1С выбрать один штрихкод номенклатуры по приоритету формата?

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

В типовых решениях 1С (например, в «1С:Розница») для одной позиции номенклатуры может быть зарегистрировано несколько штрихкодов: собственные внутренние коды, коды производителей формата EAN-13, короткие EAN-8 или коды других стандартов. В стандартной обработке печати ценников и этикеток штрихкод часто выбирается агрегатной функцией МАКСИМУМ(Штрихкод), что не учитывает бизнес-логику приоритетов.

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

  1. Внутренний штрихкод организации (префикс «2», формат EAN-13);
  2. Внешний штрихкод производителя формата EAN-13;
  3. Штрихкод формата EAN-8;
  4. Все остальные типы штрихкодов.

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

Способ 1. Использование временной таблицы и группировки по минимальному приоритету

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

  1. Вычисляем числовой приоритет для каждого штрихкода с помощью конструкции ВЫБОР КОГДА ... ТОГДА ... КОНЕЦ и сохраняем результат во временную таблицу.
  2. Во вложенном подзапросе определяем минимальное значение приоритета для каждой связки ключевых полей (Номенклатура, Характеристика, Упаковка).
  3. Соединяем исходную временную таблицу с подзапросом по ключевым полям и значению минимального приоритета, извлекая результирующий штрихкод.

Посмотрим на пример реализации запроса:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    Штрихкоды.Владелец КАК Номенклатура,
    Штрихкоды.Характеристика КАК Характеристика,
    Штрихкоды.Упаковка КАК Упаковка,
    Штрихкоды.Штрихкод КАК Штрихкод,
    ВЫБОР
        КОГДА Штрихкоды.ТипШтрихкода = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ТипыШтрихкодов.EAN13)
            ТОГДА ВЫБОР
                КОГДА ПОДСТРОКА(Штрихкоды.Штрихкод, 1, 1) = "2"
                    ТОГДА 1
                ИНАЧЕ 2
            КОНЕЦ
        КОГДА Штрихкоды.ТипШтрихкода = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ТипыШтрихкодов.EAN8)
            ТОГДА 3
        ИНАЧЕ 4
    КОНЕЦ КАК Приоритет
ПОМЕСТИТЬ ВТ_ШтрихкодыСПриоритетом
ИЗ
    РегистрСведений.Штрихкоды КАК Штрихкоды
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_Штрихкоды.Номенклатура КАК Номенклатура,
    ВТ_Штрихкоды.Характеристика КАК Характеристика,
    ВТ_Штрихкоды.Упаковка КАК Упаковка,
    МИНИМУМ(ВТ_Штрихкоды.Штрихкод) КАК Штрихкод
ИЗ
    ВТ_ШтрихкодыСПриоритетом КАК ВТ_Штрихкоды
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ (
        ВЫБРАТЬ
            ВТ_Мин.Номенклатура КАК Номенклатура,
            ВТ_Мин.Характеристика КАК Характеристика,
            ВТ_Мин.Упаковка КАК Упаковка,
            МИНИМУМ(ВТ_Мин.Приоритет) КАК Приоритет
        ИЗ
            ВТ_ШтрихкодыСПриоритетом КАК ВТ_Мин
        СГРУППИРОВАТЬ ПО
            ВТ_Мин.Номенклатура,
            ВТ_Мин.Характеристика,
            ВТ_Мин.Упаковка
    ) КАК МинПриоритет
    ПО ВТ_Штрихкоды.Номенклатура = МинПриоритет.Номенклатура
        И ВТ_Штрихкоды.Характеристика = МинПриоритет.Характеристика
        И ВТ_Штрихкоды.Упаковка = МинПриоритет.Упаковка
        И ВТ_Штрихкоды.Приоритет = МинПриоритет.Приоритет
СГРУППИРОВАТЬ ПО
    ВТ_Штрихкоды.Номенклатура,
    ВТ_Штрихкоды.Характеристика,
    ВТ_Штрихкоды.Упаковка

Обратите внимание: если у номенклатуры окажется несколько штрихкодов с одинаковым приоритетом (например, два внешних кода EAN-13), группировка с функцией МИНИМУМ(ВТ_Штрихкоды.Штрихкод) гарантирует возврат ровно одной записи.

Способ 2. Оптимизированный однопроходный запрос через строковую свертку

В языке запросов платформы 1С нет аналитических оконных функций, однако можно избежать создания лишних временных таблиц и соединения подзапросов. Для этого применим строковую конкатенацию веса приоритета со значением штрихкода.

Выясним логику работы этого метода:

  1. Формируем составную строку: первым символом идет строковый вес (например, "1", "2", "3", "4"), а следом — сам штрихкод.
  2. При вычислении МИНИМУМ() по составной строке СУБД сначала сравнивает ведущий символ приоритета, а при совпадении — алфавитный порядок самого штрихкода.
  3. Во внешнем запросе отсекаем первый символ с помощью функции ПОДСТРОКА() и получаем исходный штрихкод.

Рассмотрим пример компактного запроса без тяжелых соединений:


ВЫБРАТЬ
    СвернутыеШтрихкоды.Номенклатура КАК Номенклатура,
    СвернутыеШтрихкоды.Характеристика КАК Характеристика,
    СвернутыеШтрихкоды.Упаковка КАК Упаковка,
    ПОДСТРОКА(СвернутыеШтрихкоды.СоставнойШтрихкод, 2, 200) КАК Штрихкод
ИЗ
    (
        ВЫБРАТЬ
            Штрихкоды.Владелец КАК Номенклатура,
            Штрихкоды.Характеристика КАК Характеристика,
            Штрихкоды.Упаковка КАК Упаковка,
            МИНИМУМ(
                ВЫБОР
                    КОГДА Штрихкоды.ТипШтрихкода = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ТипыШтрихкодов.EAN13)
                        ТОГДА ВЫБОР
                            КОГДА ПОДСТРОКА(Штрихкоды.Штрихкод, 1, 1) = "2"
                                ТОГДА "1" + Штрихкоды.Штрихкод
                            ИНАЧЕ "2" + Штрихкоды.Штрихкод
                        КОНЕЦ
                    КОГДА Штрихкоды.ТипШтрихкода = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ТипыШтрихкодов.EAN8)
                        ТОГДА "3" + Штрихкоды.Штрихкод
                    ИНАЧЕ "4" + Штрихкоды.Штрихкод
                КОНЕЦ
            ) КАК СоставнойШтрихкод
        ИЗ
            РегистрСведений.Штрихкоды КАК Штрихкоды
        СГРУППИРОВАТЬ ПО
            Штрихкоды.Владелец,
            Штрихкоды.Характеристика,
            Штрихкоды.Упаковка
    ) КАК СвернутыеШтрихкоды

Рекомендации по оптимизации производительности

При внедрении запроса в схему компоновки данных типовой обработки обратите внимание на следующие моменты:

  1. Ограничение выборки: Не считывайте весь регистр сведений РегистрСведений.Штрихкоды целиком. Обязательно накладывайте отбор по таблице товаров, отправленных на печать ценников (через условие ГДЕ Штрихкоды.Владелец В (...) или соединение с исходной таблицей товаров).
  2. Индексация: Если используется первый способ с временными таблицами, укажите директиву ИНДЕКСИРОВАТЬ ПО Номенклатура, Характеристика, Упаковка, Приоритет для таблицы ВТ_ШтрихкодыСПриоритетом, чтобы ускорить внутреннее соединение.
← На главную