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

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

В практике программиста 1С часто возникает ситуация, когда внешние данные (из Excel, CSV или TXT файлов) не полностью соответствуют формату хранения данных в информационной базе. Типичный пример — работа с артикулами или кодами товаров. В базе данных артикул может храниться как строка фиксированной длины с лидирующими нулями (например, 00002255), в то время как в файле загрузки указано лишь значимое число (2255). Когда справочник Номенклатура разрастается до миллионов записей, обычный перебор становится невозможным, и задачу приходится решать на уровне запросов.

В данной статье мы подробно разберем несколько стратегий решения этой задачи: от простого использования оператора ПОДОБНО до профессиональной оптимизации с использованием расширений и новых функций платформы.

Метод 1. Использование оператора ПОДОБНО с предварительной подготовкой данных

Проанализируем стандартную ошибку начинающих разработчиков. Часто пытаются написать условие связи или фильтрации напрямую, используя конструкцию вида Артикул ПОДОБНО "%" + втДанные.Артикул. Однако язык запросов 1С накладывает определенные ограничения на использование строковых функций в условиях соединения. Рассмотрим наиболее корректный путь реализации этого метода через временные таблицы.

Основная проблема здесь заключается в том, что функция ВЫРАЗИТЬ(Поле КАК СТРОКА(20)) может дополнять строку пробелами справа до указанной длины. Если мы попытаемся сопоставить "%255 " (с пробелами), запрос не найдет соответствия с "00000255". Чтобы этого избежать, нам нужно подготовить "чистый" шаблон поиска.

Разберем по шагам, как подготовить данные во временной таблице:


// Шаг 1: Загружаем данные из файла в таблицу значений и передаем в запрос
// Допустим, в ТЗ поле Артикул уже имеет тип Строка без лишних пробелов

Запрос = Новый Запрос;
Запрос.МенеджерВременных Таблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст = 
"ВЫБРАТЬ
|	" + """%""" + " + ТЗ.Артикул КАК ШаблонПоиска,
|	ТЗ.Артикул КАК ИсходныйАртикул
|ПОМЕСТИТЬ ВТ_КритерииПоиска
|ИЗ
|	&ТЗ КАК ТЗ";

Запрос.УстановитьПараметр("ТЗ", ТаблицаИзФайла);
Запрос.Выполнить();

// Шаг 2: Основной запрос с использованием ПОДОБНО
Запрос.Текст = 
"ВЫБРАТЬ
|	Номенклатура.Ссылка КАК Товар,
|	ВТ.ИсходныйАртикул
|ИЗ
|	Справочник.Номенклатура КАК Номенклатура
|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_КритерииПоиска КАК ВТ
|		ПО Номенклатура.Артикул ПОДОБНО ВТ.ШаблонПоиска
|ГДЕ
|	НЕ Номенклатура.ЭтоГруппа";

Важный нюанс: Чтобы этот метод работал, в исходной таблице значений колонке должен быть явно назначен тип ОписаниеТипов("Строка") без ограничения длины (переменная длина), тогда СУБД не будет добавлять лишние пробелы в хвост строки.

Метод 2. Программное дополнение нулями (Самый быстрый метод)

Проанализируем ситуацию с точки зрения производительности. Использование оператора ПОДОБНО с символом "%" в начале строки — это "смерть" для производительности на миллионных таблицах. SQL-сервер не может использовать индекс по полю Артикул, если поиск идет не по началу строки. В результате система будет выполнять полное сканирование таблицы (Full Table Scan), что приведет к зависанию системы при больших объемах.

Выясним причину, почему бы не сделать наоборот? Вместо того чтобы пытаться "обрезать" нули в базе, мы можем "дополнить" артикул из файла нулями до нужной длины еще на этапе формирования таблицы значений. Если мы знаем, что в базе артикул всегда имеет длину 8 символов, мы можем преобразовать 2255 в 00002255 программно.

Рассмотрим пример подготовки данных на языке 1С:


Для Каждого СтрокаТЗ Из ТаблицаИзФайла Цикл
    // Дополняем строку нулями слева до 8 символов
    АртикулДляПоиска = СтрокаТЗ.Артикул;
    Пока СтрДлина(АртикулДляПоиска) < 8 Цикл
        АртикулДляПоиска = "0" + АртикулДляПоиска;
    КонецЦикла;
    СтрокаТЗ.Артикул = АртикулДляПоиска;
КонецЦикла;

Теперь в запросе мы можем использовать прямое соединение, которое работает мгновенно:


"ВЫБРАТЬ
|	Номенклатура.Ссылка
|ИЗ
|	Справочник.Номенклатура КАК Номенклатура
|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ &ТЗ КАК ВТ
|		ПО Номенклатура.Артикул = ВТ.Артикул"

Этот метод является предпочтительным, так как он использует индексы базы данных и обеспечивает максимальную скорость работы даже на очень больших справочниках.

Метод 3. Новые функции платформы (версия 8.3.20 и выше)

Если вы работаете на современной платформе (начиная с версии 8.3.20), мы можем использовать расширенные функции языка запросов для работы со строками. Посмотрим на новые возможности, которые позволяют очищать строки прямо в теле запроса.

Хотя функция СОКРЛ (удаление пробелов слева) напрямую не удаляет нули, она в сочетании с другими манипуляциями позволяет более гибко управлять строками. Однако для удаления именно лидирующих нулей в самом запросе без использования ПОДОБНО всё еще нет единой функции, поэтому предыдущие методы остаются актуальными.

Тем не менее, полезно знать о наличии функций:

  1. СОКРЛП(Поле) — удаляет пробелы с обеих сторон.
  2. ДЛИНА(Поле) — позволяет вычислять длину строки для более сложных условий.

Метод 4. Оптимизация через расширение (для типовых конфигураций)

Если конфигурация типовая и находится "на замке", а задача сопоставления артикулов выполняется часто, мы можем применить механизм Расширений. Это позволит нам добавить новое индексированное поле, не меняя основную конфигурацию.

Разберем этот профессиональный подход по шагам:

  1. Создаем расширение конфигурации.
  2. Добавляем в расширение справочник Номенклатура.
  3. Добавляем новый реквизит АртикулЧислом (тип Число) или АртикулБезНулей (тип Строка).
  4. Устанавливаем свойство "Индексировать" для нового реквизита.
  5. В модуле объекта (через расширение) в процедуре ПередЗаписью прописываем логику заполнения этого поля на основе основного артикула.
  6. Один раз запускаем обработку, которая заполнит это поле для всей существующей номенклатуры.

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


"ВЫБРАТЬ
|	Номенклатура.Ссылка
|ИЗ
|	Справочник.Номенклатура КАК Номенклатура
|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ &ВТ_ДанныеФайла КАК ВТ
|		ПО Номенклатура.АртикулЧислом = ВТ.АртикулЧислом"

Подведение итогов

Проанализировав все способы, можно сделать следующие выводы. Для разовых задач или небольших справочников вполне подходит Метод 1 с использованием оператора ПОДОБНО, при условии корректной подготовки шаблона во временной таблице. Однако для постоянной работы с большими данными (более 1 млн записей) критически важно обеспечить использование индексов.

Рекомендация: Если длина артикула в базе фиксированная, используйте Метод 2 (дополнение нулями в коде 1С перед запросом). Если же форматы артикулов в базе разные и непредсказуемые, рассмотрите Метод 4 с добавлением индексированного реквизита в расширении. Это позволит сохранить типовую конфигурацию в чистоте и обеспечит мгновенную работу отчетов о продажах.

← На главную