Как в запросе 1С посчитать количество символов или отобрать строки по длине

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

При работе с запросами в системе 1С:Предприятие 8 программисты часто сталкиваются с существенным ограничением: встроенный язык запросов не содержит прямой функции ДЛИНА() или LEN(), которая могла бы вернуть количество символов в строковом поле. Это связано с тем, что язык запросов 1С ориентирован на кроссплатформенность и транслируется в SQL-запросы, специфичные для различных СУБД (MS SQL, PostgreSQL, Oracle, IBM DB2), где работа со строками может отличаться.

Тем не менее, задачу подсчета символов или фильтрации по длине реквизита (например, Артикула или Кода) можно решить несколькими способами. В этой статье мы подробно разберем все доступные методы — от самых простых до наиболее продвинутых и точных.

Способ 1. Использование оператора ПОДОБНО (Фильтрация по длине)

Если ваша задача состоит не в получении числа, а в простом отборе строк определенной длины, наиболее эффективным методом будет использование оператора ПОДОБНО с использованием спецсимвола подчеркивания (_), который в шаблоне заменяет ровно один произвольный символ.

Допустим, нам нужно отобрать артикулы, состоящие ровно из 9 символов. Рассмотрим, как это реализовать:


ГДЕ
    Номенклатура.Артикул ПОДОБНО "_________"
    И НЕ Номенклатура.Артикул ПОДОБНО "__________%"

Важные нюансы этого метода:

  1. Одно подчеркивание _ соответствует одному символу.
  2. Процент % соответствует любой последовательности символов.
  3. Если в базе данных используются строки фиксированной длины, 1С может дополнять их пробелами. Чтобы исключить попадание строк с пробелами в конце, в шаблоне можно использовать конструкцию [^ ] (любой символ, кроме пробела).

Пример более точного отбора для 9 символов, чтобы не попали строки с «хвостовыми» пробелами:


ГДЕ
    Номенклатура.Артикул ПОДОБНО "[^ ][^ ][^ ][^ ][^ ][^ ][^ ][^ ][^ ]"

Способ 2. Сравнение через ПОДСТРОКА

Проанализируем ситуацию, когда нам нужно проверить, имеет ли строка длину не менее N символов. Для этого удобно использовать функцию ПОДСТРОКА. Особенность этой функции в 1С заключается в том, что если запрошенная длина превышает реальную длину строки, ошибка не возникает — возвращается вся имеющаяся строка.

Для отбора строк длиной ровно 10 символов мы можем сравнить результат обрезки до 10-го и до 9-го символа:


ВЫБРАТЬ
    Номенклатура.Наименование
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.Артикул = ПОДСТРОКА(Номенклатура.Артикул, 1, 10)
    И Номенклатура.Артикул <> ПОДСТРОКА(Номенклатура.Артикул, 1, 9)

В данном примере первое условие отсекает строки длиннее 10 символов, а второе условие гарантирует, что строка не короче 10 символов.

Способ 3. Использование конструкции ВЫРАЗИТЬ

Разберем еще один интересный «маневр» с использованием типизации строк. Оператор ВЫРАЗИТЬ позволяет привести строку к фиксированной длине. Если реальная строка длиннее указанного значения, она будет обрезана.

Посмотрим на пример отбора строк, длина которых не превышает 5 символов:


ГДЕ
    Номенклатура.Артикул = ВЫРАЗИТЬ(Номенклатура.Артикул КАК СТРОКА(5))

Если артикул имеет 6 символов, то ВЫРАЗИТЬ обрежет его до 5, и сравнение вернет ложь. Если же в артикуле 3 символа, то сравнение вернет истину (в зависимости от настроек СУБД могут добавиться пробелы, поэтому метод стоит тестировать на конкретной конфигурации).

Способ 4. Получение точного числа (Метод «Лесенки»)

Если нам необходимо именно числовое значение длины (например, для вычислений в отчете), мы можем использовать вложенную конструкцию ВЫБОР КОГДА. Это решение громоздкое, но рабочее для строк с ограниченной максимальной длиной.


ВЫБРАТЬ
    Номенклатура.Артикул,
    ВЫБОР
        КОГДА ПОДСТРОКА(Номенклатура.Артикул, 10, 1) <> "" ТОГДА 10
        КОГДА ПОДСТРОКА(Номенклатура.Артикул, 9, 1) <> "" ТОГДА 9
        КОГДА ПОДСТРОКА(Номенклатура.Артикул, 8, 1) <> "" ТОГДА 8
        ИНАЧЕ 0
    КОНЕЦ КАК ДлинаАртикула
ИЗ
    Справочник.Номенклатура

Обратите внимание: проверку нужно начинать с максимального возможного числа и двигаться в сторону уменьшения (убывания), иначе условие для 1-го символа всегда будет срабатывать первым.

Способ 5. Универсальный расчет через таблицу чисел (Продвинутый уровень)

Проанализируем самый мощный метод, который позволяет вычислить длину любой строки без написания сотен строк условий. Идея заключается в декартовом произведении вашей таблицы с вспомогательной таблицей чисел (индексов). Мы находим максимальный индекс, для которого символ в строке не является «пустышкой».

Ниже приведен пример пакетного запроса для определения длины строки до 64 символов:


// Создаем таблицу чисел от 0 до 63
ВЫБРАТЬ 0 КАК ё ПОМЕСТИТЬ Р0 ОБЪЕДИНИТЬ ВЫБРАТЬ 1;
ВЫБРАТЬ 2 * Р1.ё + Р0.ё КАК ё ПОМЕСТИТЬ Р10 ИЗ Р0 КАК Р1, Р0 КАК Р0;
ВЫБРАТЬ 4 * Р32.ё + Р10.ё КАК ё ПОМЕСТИТЬ Р3210 ИЗ Р10 КАК Р32, Р10 КАК Р10;
ВЫБРАТЬ 16 * Р54.ё + Р3210.ё + 1 КАК ё ПОМЕСТИТЬ ТаблицаЧисел ИЗ Р10 КАК Р54, Р3210 КАК Р3210;

// Основной запрос
ВЫБРАТЬ
    Источник.Артикул КАК Строка,
    МАКСИМУМ(ТаблицаЧисел.ё) КАК ДлинаСтроки
ИЗ
    Справочник.Номенклатура КАК Источник,
    ТаблицаЧисел КАК ТаблицаЧисел
ГДЕ
    ПОДСТРОКА(Источник.Артикул, ТаблицаЧисел.ё, 1) <> ""
СГРУППИРОВАТЬ ПО
    Источник.Артикул

Этот метод работает следующим образом: мы соединяем каждую строку артикула с каждым числом из таблицы. Затем оставляем только те пары, где в артикуле на позиции «число» есть реальный символ. Сгруппировав по артикулу и взяв максимум от числа, мы получаем точную длину.

Способ 6. Система компоновки данных (СКД)

Если вы разрабатываете отчет на базе СКД, вам не нужно мучить запрос сложными конструкциями. В СКД на уровне вычисляемых полей или выражений ресурсов доступна функция ДЛИНАСТРОКИ(). Это самый правильный и производительный способ, если данные нужны только для вывода в отчет.

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

Выясним причину, почему использование вышеуказанных методов в больших таблицах может быть опасным. Все манипуляции со строками (ПОДОБНО, ПОДСТРОКА, ВЫРАЗИТЬ) в секции ГДЕ приводят к тому, что СУБД не может использовать индексы (происходит Full Table Scan). Если в вашей таблице сотни тысяч записей, такие запросы будут выполняться медленно.

Лучшая практика (Best Practice):

Если в вашей бизнес-логике часто требуется поиск или отбор по длине строки, рекомендуется добавить в справочник или документ дополнительный числовой реквизит (например, АртикулДлина). Заполняйте его программно в обработчике события ПередЗаписью объекта:


Процедура ПередЗаписью(Отказ)
    АртикулДлина = СтрДлина(СокрЛП(Артикул));
КонецПроцедуры

В этом случае ваш запрос станет максимально простым и быстрым:

ГДЕ Номенклатура.АртикулДлина = 9

Этот подход экономит ресурсы сервера и обеспечивает мгновенный отклик системы даже при огромных объемах данных.

← На главную