Разработка и Конфигурация · 12 мин
ВЫБОР КОГДА и ПОДСТРОКА в запросе 1С: синтаксис и практика
Как использовать ВЫБОР КОГДА и ПОДСТРОКА в запросах 1С: синтаксис, примеры выборки, типичные ошибки с типами данных и производительностью, проверка результата.
Конструкция ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ ... КОНЕЦ в языке запросов 1С — это аналог оператора CASE в SQL. Она позволяет вернуть разные значения в одном поле результата в зависимости от условия. Функция ПОДСТРОКА извлекает часть строки по позиции и длине, а в связке с ВЫБОР КОГДА решает типовую задачу: взять из длинной строки только нужный фрагмент и при этом обработать ситуации, когда строка короче ожидаемой или пуста.
Практический сценарий выглядит так: в справочнике хранятся наименования вида «Товар/Артикул/Поставщик», и в отчёте нужно вывести только первую часть до разделителя, а если разделителя нет — вывести строку целиком. Или номер документа содержит префикс, который надо отрезать, но только если он действительно присутствует. Обе задачи решаются комбинацией ПОДСТРОКА и условной логики прямо в запросе, без постобработки в коде.
Важно понимать ограничение: в языке запросов 1С нет функции поиска позиции подстроки (аналога CHARINDEX/INSTR) и нет регулярных выражений. Поэтому ПОДСТРОКА применяется там, где позиция известна или фиксирована, а поиск вхождения выполняется через оператор ПОДОБНО в условии. Это определяет, какие задачи решаются в запросе, а какие проще вынести в код модуля.
Синтаксис ВЫБОР КОГДА в языке запросов
Полная форма конструкции выглядит так: ВЫБОР КОГДА условие1 ТОГДА значение1 КОГДА условие2 ТОГДА значение2 ИНАЧЕ значение_по_умолчанию КОНЕЦ. Ветвей КОГДА может быть сколько угодно, проверяются они сверху вниз, срабатывает первая истинная. Ветвь ИНАЧЕ необязательна, но без неё при несовпадении всех условий поле вернёт NULL — это частая причина «пустых» колонок в отчётах.
Есть и сокращённая форма: ВЫБОР выражение КОГДА значение1 ТОГДА результат1 ... КОНЕЦ, где выражение сравнивается на равенство с каждым вариантом. Она удобна для перечислений и статусов, но не работает с условиями типа ПОДОБНО или сравнениями «больше/меньше» — для них нужна полная форма.
Ключевое требование, о котором часто забывают: все ветви ТОГДА и ИНАЧЕ должны возвращать значения совместимых типов. Если одна ветвь возвращает строку, а другая — число, запрос либо не выполнится, либо приведёт типы непредсказуемо в зависимости от СУБД. Явно приводите типы через ВЫРАЗИТЬ, когда результат должен быть строго определённого типа, например для поля компоновки данных.
Функция ПОДСТРОКА: параметры и поведение
Синтаксис: ПОДСТРОКА(Строка, НачальнаяПозиция, Длина). Нумерация символов начинается с единицы, а не с нуля — это отличие от большинства языков программирования и источник ошибок «смещения на один символ». Например, ПОДСТРОКА(Номер, 3, 5) вернёт пять символов, начиная с третьего.
Если начальная позиция больше длины строки, результат — пустая строка, а не ошибка. Если запрошенная длина выходит за конец строки, вернётся всё до конца строки без ошибки. Это упрощает обработку коротких значений, но маскирует проблемы данных: запрос отработает «успешно», а поле окажется пустым или обрезанным.
Для проверки длины строки в запросе нет прямой функции ДЛИНА в стандартном языке запросов. Обходной приём — сравнение через ПОДСТРОКА: выражение ПОДСТРОКА(Поле, 11, 1) = "" фактически проверяет, что строка короче 11 символов. Этот приём широко используется для валидации ИНН, кодов и номеров фиксированной длины.
Типовой пример: извлечь подстроку по условию
Задача: из номера документа убрать двухсимвольный префикс, но только если он есть. Предположим, префиксированные номера начинаются с букв, а обычные — с цифр. Запрос:
ВЫБРАТЬ
ВЫБОР
КОГДА Реализация.Номер ПОДОБНО "[А-ЯA-Z][А-ЯA-Z]%"
ТОГДА ПОДСТРОКА(Реализация.Номер, 3, 20)
ИНАЧЕ Реализация.Номер
КОНЕЦ КАК НомерБезПрефикса
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
Здесь шаблон ПОДОБНО проверяет, что первые два символа — буквы. Если условие истинно, берём подстроку с третьей позиции с запасом по длине (20 символов — лишнее просто отсекается). Иначе возвращаем номер как есть. Результат — одна колонка с нормализованными номерами, пригодная для сортировки и соединений.
Второй пример — извлечение части наименования фиксированной структуры. Если код товара всегда занимает первые 6 символов наименования, а для строк, где код не заполнен, стоит пробел, можно написать: ВЫБОР КОГДА ПОДСТРОКА(Наименование, 1, 1) = " " ТОГДА "" ИНАЧЕ ПОДСТРОКА(Наименование, 1, 6) КОНЕЦ. Условие защищает от мусора в данных, где структура не соблюдена.
ВЫБОР
КОГДА Контрагент.ИНН ПОДОБНО "__________"
ТОГДА ПОДСТРОКА(Контрагент.ИНН, 1, 10)
КОГДА Контрагент.ИНН ПОДОБНО "____________"
ТОГДА ПОДСТРОКА(Контрагент.ИНН, 1, 12)
ИНАЧЕ "Некорректный ИНН"
КОНЕЦ КАК ИННПровереноКак искать вхождение подстроки: ПОДОБНО и его ограничения
Для проверки «содержит ли строка подстроку» в запросе используется оператор ПОДОБНО с шаблоном: ГДЕ Наименование ПОДОБНО "%кабель%". Символ % означает любую последовательность символов, подчёркивание _ — ровно один символ, квадратные скобки — диапазон или набор. Это единственный инструмент поиска по содержимому, доступный в языке запросов.
Главное ограничение: ПОДОБНО проверяет факт вхождения, но не сообщает позицию. Поэтому конструкция «вырезать всё до первого слэша» в чистом запросе невозможна — позиция слэша неизвестна. Варианты решения: если разделитель всегда на фиксированной позиции, используйте ПОДСТРОКА напрямую; если позиция плавает, выгружайте результат и обрабатывайте функцией СтрНайти в коде, либо нормализуйте данные при записи, вынося нужную часть в отдельный реквизит.
Ещё одна ловушка — спецсимволы в самом шаблоне. Если искомый текст содержит %, _ или скобки, их нужно экранировать через специальный синтаксис СПЕЦСИМВОЛ: ПОДОБНО "%[~]%" СПЕЦСИМВОЛ "~". Без экранирования запрос найдёт лишнее или ничего не найдёт, и ошибка будет неочевидна.
Как выбрать подход
Типичные ошибки и как их избежать
Первая ошибка — смешение типов в ветвях ВЫБОР. Когда одна ветвь возвращает строку, а другая число или ссылку, запрос может упасть на исполнении или вернуть неожиданный тип поля, что ломает СКД и выгрузку в таблицу значений. Правило: приводите ветви к одному типу через ВЫРАЗИТЬ или возвращайте строковое представление везде.
Вторая ошибка — сравнение с NULL. Условие КОГДА Поле = NULL никогда не истинно: в логике запросов любое сравнение с NULL даёт неопределённость. Правильно — КОГДА Поле ЕСТЬ NULL. Это особенно важно при левых соединениях, где отсутствующие записи дают NULL в полях присоединённой таблицы, и ВЫБОР КОГДА используется для подстановки значения по умолчанию.
Третья ошибка — нумерация с нуля. Разработчики, пришедшие из других языков, пишут ПОДСТРОКА(Поле, 0, 5) и получают сдвиг или пустой результат. В языке запросов 1С первый символ — позиция 1. Проверяйте результат на одном тестовом значении через консоль запросов, прежде чем встраивать выражение в рабочий отчёт.
Производительность и безопасные границы
Условия с ПОДОБНО, где шаблон начинается с %, не используют индексы и приводят к полному сканированию таблицы. На справочнике в несколько тысяч записей это незаметно, на таблице движений с миллионами строк — запрос может выполняться минутами. Если фильтрация по подстроке нужна постоянно, рассмотрите хранение поискового фрагмента в отдельном индексированном реквизите.
Выражения ВЫБОР КОГДА и ПОДСТРОКА в секции выборки вычисляются на стороне СУБД и сами по себе дёшевы. Дорого становится, когда то же выражение попадает в ГДЕ или в условие соединения: СУБД не может применить индекс к вычисляемому значению. По возможности фильтруйте по исходным полям, а преобразование делайте только в списке выборки.
Перед изменением рабочего запроса в продуктивной базе проверьте новый вариант на копии или хотя бы в консоли запросов с реальными данными. Ошибка в условии не разрушит данные — запросы только читают, — но некорректный отчёт, ушедший пользователям, приведёт к неверным решениям по учёту. Для запросов, участвующих в обменах и проведении документов, тестирование на копии обязательно.
Как проверить результат
Одинаковый тип во всех строках, СКД и выгрузка работают
Смешанные типы, ошибки при выгрузке в таблицу значений
Возвращается значение из ИНАЧЕ
Пустые значения NULL там, где их не ждали
ПОДСТРОКА возвращает пустую строку или обрезанную часть без ошибки
Неожиданные значения из-за смещения позиции
Запрос отрабатывает за приемлемое время на реальном объёме
Полное сканирование таблицы из-за ПОДОБНО с ведущим %
Проверка результата и отладка
Отлаживать сложные выражения удобнее по частям. Сначала выведите исходное поле и промежуточные значения: само условие как булево, результат ПОДСТРОКА отдельной колонкой. Когда видно, что условие срабатывает на ожидаемых строках, собирайте итоговое ВЫБОР КОГДА. Такой пошаговый подход быстрее, чем отладка монолитного выражения.
Полезный приём — добавить в запрос счётчик строк по ветвям: сгруппировать результат по вычисляемому полю и посмотреть количество записей в каждой категории. Если ветвь «некорректное значение» неожиданно велика, проблема в данных, а не в запросе. Это сразу показывает, стоит ли чинить запрос или запускать обработку очистки данных.
- 1Откройте консоль запросов и выведите исходное поле без преобразований
- 2Добавьте условие ПОДОБНО отдельной колонкой и проверьте, что оно срабатывает на нужных строках
- 3Добавьте ПОДСТРОКА с нужной позицией и проверьте смещение на нескольких примерах
- 4Соберите ВЫБОР КОГДА с ветвью ИНАЧЕ и проверьте тип результата
- 5Выполните запрос на полном объёме данных и оцените время выполнения
Что важно запомнить
ВЫБОР КОГДА возвращает значения по условию и требует совместимых типов во всех ветвях. ПОДСТРОКА извлекает фрагмент с позиции, начиная с 1. Поиск вхождения выполняется только через ПОДОБНО без получения позиции. Проверяйте NULL через ЕСТЬ NULL и тестируйте выражения в консоли перед внедрением.
Частые вопросы
Можно ли найти позицию подстроки прямо в запросе 1С?
Нет, в языке запросов нет функции поиска позиции вхождения. Оператор ПОДОБНО только проверяет соответствие шаблону. Если позиция нужна, обрабатывайте строку в коде через СтрНайти после выполнения запроса или храните нужный фрагмент в отдельном реквизите.
Почему ВЫБОР КОГДА возвращает NULL, хотя условие должно сработать?
Чаще всего причина в сравнении с NULL через знак равенства — такое условие никогда не истинно. Замените на ЕСТЬ NULL. Вторая причина — отсутствие ветви ИНАЧЕ: если ни одно условие не сработало, результат по умолчанию NULL.
Как сравнить только часть строки в условии ГДЕ?
Используйте ПОДСТРОКА в самом условии: ГДЕ ПОДСТРОКА(Поле, 1, 2) = "АБ". Учтите, что такое условие не использует индекс, поэтому на больших таблицах фильтрация будет медленной. Альтернатива — шаблон ПОДОБНО "АБ%", который в ряде случаев индекс использовать может.
Регистронезависим ли оператор ПОДОБНО?
Поведение зависит от используемой СУБД и её настроек сортировки. На большинстве типовых конфигураций сравнение оказывается регистронезависимым, но гарантировать это для всех СУБД нельзя. Если регистр критичен, тестируйте на целевой базе или приводите данные к единому регистру при записи.
Можно ли использовать ВЫБОР КОГДА в параметрах виртуальной таблицы?
Да, выражения допустимы в параметрах виртуальных таблиц, в условиях ГДЕ, в группировках и соединениях. Однако сложные выражения в параметрах виртуальных таблиц могут ухудшить план запроса, поэтому простые значения предпочтительнее.
Что вернёт ПОДСТРОКА, если позиция больше длины строки?
Пустую строку, без ошибки выполнения. Это удобно для обработки неоднородных данных, но маскирует проблемы: проверяйте наличие пустых результатов в отладочной выборке, чтобы не пропустить некорректные исходные значения.