В практике программиста 1С часто возникает ситуация, когда внешние данные (из Excel, CSV или TXT файлов) не полностью соответствуют формату хранения данных в информационной базе. Типичный пример — работа с артикулами или кодами товаров. В базе данных артикул может храниться как строка фиксированной длины с лидирующими нулями (например, 00002255), в то время как в файле загрузки указано лишь значимое число (2255). Когда справочник Номенклатура разрастается до миллионов записей, обычный перебор становится невозможным, и задачу приходится решать на уровне запросов.
В данной статье мы подробно разберем несколько стратегий решения этой задачи: от простого использования оператора ПОДОБНО до профессиональной оптимизации с использованием расширений и новых функций платформы.
Проанализируем стандартную ошибку начинающих разработчиков. Часто пытаются написать условие связи или фильтрации напрямую, используя конструкцию вида Артикул ПОДОБНО "%" + втДанные.Артикул. Однако язык запросов 1С накладывает определенные ограничения на использование строковых функций в условиях соединения. Рассмотрим наиболее корректный путь реализации этого метода через временные таблицы.
Основная проблема здесь заключается в том, что функция ВЫРАЗИТЬ(Поле КАК СТРОКА(20)) может дополнять строку пробелами справа до указанной длины. Если мы попытаемся сопоставить "%255 " (с пробелами), запрос не найдет соответствия с "00000255". Чтобы этого избежать, нам нужно подготовить "чистый" шаблон поиска.
Разберем по шагам, как подготовить данные во временной таблице:
// Шаг 1: Загружаем данные из файла в таблицу значений и передаем в запрос
// Допустим, в ТЗ поле Артикул уже имеет тип Строка без лишних пробелов
Запрос = Новый Запрос;
Запрос.МенеджерВременных Таблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст =
"ВЫБРАТЬ
| " + """%""" + " + ТЗ.Артикул КАК ШаблонПоиска,
| ТЗ.Артикул КАК ИсходныйАртикул
|ПОМЕСТИТЬ ВТ_КритерииПоиска
|ИЗ
| &ТЗ КАК ТЗ";
Запрос.УстановитьПараметр("ТЗ", ТаблицаИзФайла);
Запрос.Выполнить();
// Шаг 2: Основной запрос с использованием ПОДОБНО
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Товар,
| ВТ.ИсходныйАртикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_КритерииПоиска КАК ВТ
| ПО Номенклатура.Артикул ПОДОБНО ВТ.ШаблонПоиска
|ГДЕ
| НЕ Номенклатура.ЭтоГруппа";
Важный нюанс: Чтобы этот метод работал, в исходной таблице значений колонке должен быть явно назначен тип ОписаниеТипов("Строка") без ограничения длины (переменная длина), тогда СУБД не будет добавлять лишние пробелы в хвост строки.
Проанализируем ситуацию с точки зрения производительности. Использование оператора ПОДОБНО с символом "%" в начале строки — это "смерть" для производительности на миллионных таблицах. SQL-сервер не может использовать индекс по полю Артикул, если поиск идет не по началу строки. В результате система будет выполнять полное сканирование таблицы (Full Table Scan), что приведет к зависанию системы при больших объемах.
Выясним причину, почему бы не сделать наоборот? Вместо того чтобы пытаться "обрезать" нули в базе, мы можем "дополнить" артикул из файла нулями до нужной длины еще на этапе формирования таблицы значений. Если мы знаем, что в базе артикул всегда имеет длину 8 символов, мы можем преобразовать 2255 в 00002255 программно.
Рассмотрим пример подготовки данных на языке 1С:
Для Каждого СтрокаТЗ Из ТаблицаИзФайла Цикл
// Дополняем строку нулями слева до 8 символов
АртикулДляПоиска = СтрокаТЗ.Артикул;
Пока СтрДлина(АртикулДляПоиска) < 8 Цикл
АртикулДляПоиска = "0" + АртикулДляПоиска;
КонецЦикла;
СтрокаТЗ.Артикул = АртикулДляПоиска;
КонецЦикла;
Теперь в запросе мы можем использовать прямое соединение, которое работает мгновенно:
"ВЫБРАТЬ
| Номенклатура.Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ &ТЗ КАК ВТ
| ПО Номенклатура.Артикул = ВТ.Артикул"
Этот метод является предпочтительным, так как он использует индексы базы данных и обеспечивает максимальную скорость работы даже на очень больших справочниках.
Если вы работаете на современной платформе (начиная с версии 8.3.20), мы можем использовать расширенные функции языка запросов для работы со строками. Посмотрим на новые возможности, которые позволяют очищать строки прямо в теле запроса.
Хотя функция СОКРЛ (удаление пробелов слева) напрямую не удаляет нули, она в сочетании с другими манипуляциями позволяет более гибко управлять строками. Однако для удаления именно лидирующих нулей в самом запросе без использования ПОДОБНО всё еще нет единой функции, поэтому предыдущие методы остаются актуальными.
Тем не менее, полезно знать о наличии функций:
СОКРЛП(Поле) — удаляет пробелы с обеих сторон.ДЛИНА(Поле) — позволяет вычислять длину строки для более сложных условий.Если конфигурация типовая и находится "на замке", а задача сопоставления артикулов выполняется часто, мы можем применить механизм Расширений. Это позволит нам добавить новое индексированное поле, не меняя основную конфигурацию.
Разберем этот профессиональный подход по шагам:
Номенклатура.АртикулЧислом (тип Число) или АртикулБезНулей (тип Строка).ПередЗаписью прописываем логику заполнения этого поля на основе основного артикула.Теперь ваш запрос будет выглядеть максимально лаконично и работать крайне быстро, так как поиск будет идти по индексированному числовому полю:
"ВЫБРАТЬ
| Номенклатура.Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ &ВТ_ДанныеФайла КАК ВТ
| ПО Номенклатура.АртикулЧислом = ВТ.АртикулЧислом"
Проанализировав все способы, можно сделать следующие выводы. Для разовых задач или небольших справочников вполне подходит Метод 1 с использованием оператора ПОДОБНО, при условии корректной подготовки шаблона во временной таблице. Однако для постоянной работы с большими данными (более 1 млн записей) критически важно обеспечить использование индексов.
Рекомендация: Если длина артикула в базе фиксированная, используйте Метод 2 (дополнение нулями в коде 1С перед запросом). Если же форматы артикулов в базе разные и непредсказуемые, рассмотрите Метод 4 с добавлением индексированного реквизита в расширении. Это позволит сохранить типовую конфигурацию в чистоте и обеспечит мгновенную работу отчетов о продажах.