К статье
Практический материал

Разработка и Конфигурация · 12 мин

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

Как преобразовать строку в число в запросе 1С: ВЫРАЗИТЬ, ПОДСТРОКА, таблица цифр, сортировка числовых строк. Примеры кода, ошибки и проверка результата.

Задача «строка как число в запросе» возникает в 1С регулярно: коды номенклатуры, артикулы, ИНН, номера документов и телефоны хранятся как строки, но сортировать, сравнивать или суммировать их нужно как числа. Проблема в том, что язык запросов 1С не имеет функции прямого преобразования строки в число — оператор ВЫРАЗИТЬ(... КАК ЧИСЛО) со строковым значением не работает и выдаёт ошибку.

Это ограничение платформы, а не ошибка разработчика. ВЫРАЗИТЬ в запросе 1С умеет только уточнять тип (например, усечь составной тип до одного ссылочного или обрезать строку до нужной длины), но не выполняет конвертацию между несовместимыми типами. Поэтому приходится использовать обходные приёмы: вычисление через подстроки, соединение со вспомогательной таблицей цифр или перенос преобразования на уровень встроенного языка.

Ниже разобраны рабочие способы преобразовать строку в число прямо в запросе, варианты для сортировки и сравнения, ограничения каждого подхода и типичные ошибки, из-за которых запрос падает или возвращает неожиданный результат.

Почему ВЫРАЗИТЬ не преобразует строку в число

Оператор ВЫРАЗИТЬ в языке запросов 1С предназначен для приведения значения к совместимому типу: сузить составное поле до одного типа ссылки, изменить длину строки, задать точность числа. Он не выполняет разбор содержимого строки. Попытка написать ВЫРАЗИТЬ(Номенклатура.Код КАК ЧИСЛО(10, 0)) завершится ошибкой исполнения запроса, потому что типы «Строка» и «Число» несовместимы для этого оператора.

По той же причине не работают арифметические трюки вроде Код + 0 или Код * 1 — в запросе 1С нет неявного приведения типов, как в некоторых СУБД. Любая арифметическая операция над строковым полем вызовет ошибку ещё на этапе исполнения.

Способ 1. Преобразование через таблицу цифр

Самый универсальный приём в чистом запросе — соединить строку с виртуальной таблицей, где каждой цифре-символу соответствует число, и собрать значение по разрядам. Идея: разбить строку на символы через ПОДСТРОКА, сопоставить каждому символу его числовое значение и сложить с учётом разряда.

Для коротких строк фиксированной длины (например, код из 5 цифр) запрос выглядит так:

ВЫБРАТЬ

Т.Код КАК Код,

Ц1.Ц 10000 + Ц2.Ц 1000 + Ц3.Ц 100 + Ц4.Ц 10 + Ц5.Ц КАК КодЧислом

ИЗ

Справочник.Номенклатура КАК Т

ЛЕВОЕ СОЕДИНЕНИЕ Цифры КАК Ц1 ПО ПОДСТРОКА(Т.Код, 1, 1) = Ц1.Символ

ЛЕВОЕ СОЕДИНЕНИЕ Цифры КАК Ц2 ПО ПОДСТРОКА(Т.Код, 2, 1) = Ц2.Символ

ЛЕВОЕ СОЕДИНЕНИЕ Цифры КАК Ц3 ПО ПОДСТРОКА(Т.Код, 3, 1) = Ц3.Символ

ЛЕВОЕ СОЕДИНЕНИЕ Цифры КАК Ц4 ПО ПОДСТРОКА(Т.Код, 4, 1) = Ц4.Символ

ЛЕВОЕ СОЕДИНЕНИЕ Цифры КАК Ц5 ПО ПОДСТРОКА(Т.Код, 5, 1) = Ц5.Символ

Таблицу «Цифры» можно получить через временную таблицу из вложенного запроса с ОБЪЕДИНИТЬ ВСЕ по десяти строкам (символ «0» — число 0, «1» — 1 и так далее) или взять из заранее созданного вспомогательного справочника. Если в строке встретится нецифровой символ, соединение не сработает и итоговое поле будет NULL — это удобно использовать как признак «грязных» данных.

Способ 2. Сортировка строки как числа через дополнение нулями

Часто преобразование нужно не само по себе, а ради правильной сортировки: строки «2», «10», «100» сортируются как «10», «100», «2». Если значения по смыслу числовые, задачу решает дополнение строки нулями слева до одинаковой длины — тогда лексикографический порядок совпадёт с числовым.

В запросе это делается через ВЫБОР по длине строки:

ВЫБРАТЬ

ВЫБОР

КОГДА ПОДСТРОКА(Т.Код, 1, 1) = "" ТОГДА "00000"

КОГДА ПОДСТРОКА(Т.Код, 2, 1) = "" ТОГДА "0000" + Т.Код

КОГДА ПОДСТРОКА(Т.Код, 3, 1) = "" ТОГДА "000" + Т.Код

КОГДА ПОДСТРОКА(Т.Код, 4, 1) = "" ТОГДА "00" + Т.Код

КОГДА ПОДСТРОКА(Т.Код, 5, 1) = "" ТОГДА "0" + Т.Код

ИНАЧЕ Т.Код

КОНЕЦ КАК КодДляСортировки

ИЗ Справочник.Номенклатура КАК Т

УПОРЯДОЧИТЬ ПО КодДляСортировки

Приём дешёвый по производительности и не требует соединений, но работает только если все строки состоят из цифр. Если в данных встречаются буквы или пробелы, порядок снова станет непредсказуемым — сначала стоит проверить данные запросом с условием на нецифровые символы.

Маршрут решения

Как выбрать действие

Нужна только сортировка или сравнение «больше-меньше» по числовым строкамИспользуйте дополнение нулями слева до одинаковой длины — это проще и быстрее соединений
Нужно арифметическое значение: сумма, среднее, диапазонСобирайте число через таблицу цифр и ПОДСТРОКА либо преобразуйте данные встроенным языком
Данные содержат буквы, пробелы, разделителиСначала очистите или нормализуйте значения, иначе любой способ даст NULL или неверный порядок
Преобразование разовое и объём данных небольшойВыгрузите результат запроса и преобразуйте через Число() в цикле встроенного языка

Способ 3. Преобразование вне запроса средствами встроенного языка

Если логика позволяет, самый надёжный путь — не мучить запрос, а преобразовать строку в число до или после него. Функция Число() встроенного языка корректно разбирает строку, а для безопасного преобразования без исключений используют попытку:

ЧисловоеЗначение = 0;

Попытка

ЧисловоеЗначение = Число(СтроковоеЗначение);

Исключение

ЧисловоеЗначение = 0;

КонецПопытки;

Типичный сценарий: запрос выбирает строковые коды, затем в цикле по выборке каждое значение преобразуется в число и помещается в таблицу значений, которая передаётся обратно в запрос как временная таблица для соединений, группировок и агрегатов. Это особенно удобно, когда нужны суммы и средние — то, что в чистом запросе по строкам недоступно.

Обратный вариант — нормализация данных заранее: обработкой создать у элемента дополнительный числовой реквизит (или дополнительный реквизит с числовым типом) и заполнить его из строкового кода. После этого все запросы работают с настоящим числом, без обходных приёмов. Это правильное долгосрочное решение, если проблема системная.

Перед выбором способа выполните контрольный запрос: выберите DISTINCT строковое поле и посмотрите, есть ли значения с буквами, пробелами, дефисами и разной длиной. В большинстве баз «числовые» коды на практике содержат 5–15% мусорных значений, и именно они ломают преобразование.
ПЗ
Практическое замечание

Сравнение и фильтрация строк как чисел

Отдельная частая задача — отбор по диапазону: «код от 100 до 200», когда код строковый. Строковое сравнение Код >= "100" И Код <= "200" даст неверный результат, потому что строка "99" по лексикографическому порядку больше строки "200" (сравнивается посимвольно, "9" больше "2").

Корректные варианты: дополнить границы диапазона и значения нулями до одинаковой длины и сравнивать строки, либо преобразовать значения в числа через таблицу цифр и фильтровать уже числа. Если длина всех кодов в базе одинаковая (например, строго 6 цифр), строковое сравнение работает корректно и без дополнения — проверьте это запросом на минимальную и максимальную длину.

Сравнение вариантов

Таблица цифр + ПОДСТРОКА

Даёт настоящее число прямо в запросе, подходит для агрегатов. Ограничение: только целые числа фиксированной длины, громоздкий текст запроса

Дополнение нулями слева

Решает сортировку и сравнение без соединений. Не даёт числового значения и не работает при смешанных буквенно-цифровых кодах

Число() во встроенном языке

Самый надёжный разбор, включая дробные и отрицательные. Требует выгрузки данных из запроса и обхода в цикле

Числовой реквизит в данных

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

Частые ошибки и как их избежать

Главная ошибка — ожидать от ВЫРАЗИТЬ поведения функции CAST из SQL. В 1С это разные вещи, и попытка сработает только в простейших конфигурациях на внешних СУБД с прямыми запросами, чего в типовой разработке быть не должно. Вторая типичная ошибка — забыть про NULL: при соединении с таблицей цифр любой нецифровой символ даёт NULL в результате, и если дальше это значение суммируется, NULL «съедает» всю сумму. Оборачивайте результат в ЕСТЬNULL(..., 0).

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

Типичные ошибки
01
ВЫРАЗИТЬ(Строка КАК ЧИСЛО) — ошибка исполнения запроса, оператор не конвертирует несовместимые типы
02
Сравнение строк разной длины как чисел без дополнения нулями — неверный порядок и неверный отбор по диапазону
03
Отсутствие ЕСТЬNULL после соединения с таблицей цифр — нецифровой символ превращает результат в NULL и ломает суммы
04
Игнорирование лидирующих пробелов и неразрывных пробелов в кодах — соединение не срабатывает на внешне «чистых» данных
05
Использование соединений по ПОДСТРОКА на больших таблицах без необходимости — запрос не использует индексы и работает медленно

Проверка результата преобразования

После внедрения любого из способов проверьте три вещи. Первое — количество строк: сравните число записей исходной таблицы и результата, если использовались соединения, чтобы убедиться, что строки не потерялись и не задвоились. Второе — доля NULL в преобразованном поле: запрос с подсчётом КОЛИЧЕСТВО(*) и КОЛИЧЕСТВО(КодЧислом) покажет, сколько значений не преобразовалось.

Третье — точечная сверка: возьмите несколько известных значений (минимальный, максимальный, типичный код) и убедитесь, что числовой результат совпадает с исходной строкой, а сортировка по числовому полю совпадает с ожидаемым порядком. Для отборов по диапазону проверьте граничные значения: коды, равные границам, должны попадать или не попадать в выборку в соответствии с использованными операторами.

Контрольные точки

Как проверить результат

Количество строк результата
Норма

Совпадает с числом строк источника

Тревожный признак

Строк меньше (потеряны при соединении) или больше (дубли)

Количество NULL в числовом поле
Норма

NULL только у заведомо нечисловых значений

Тревожный признак

NULL у значений, которые выглядят как числа — проверяйте пробелы и длину

Сортировка результата
Норма

2, 10, 100 идут в числовом порядке

Тревожный признак

Лексикографический порядок 10, 100, 2 — дополнение нулями не сработало

Границы диапазона отбора
Норма

Пограничные коды попадают в выборку по правилам операторов

Тревожный признак

Граничные значения теряются или захватываются лишние

FAQ

Можно ли в запросе 1С написать CAST или CONVERT как в SQL?

Нет, язык запросов 1С не поддерживает CAST/CONVERT. Единственный похожий оператор — ВЫРАЗИТЬ, но он только уточняет тип в рамках совместимых (ссылки, усечение строки, точность числа) и не преобразует строку в число. Используйте таблицу цифр, дополнение нулями или функцию Число() во встроенном языке.

Почему сортировка кодов выдаёт 1, 10, 100, 2 вместо числового порядка?

Потому что поле строковое и сравнение идёт посимвольно слева направо: символ «1» меньше «2», поэтому все строки, начинающиеся с единицы, оказываются раньше. Решение — дополнить значения нулями слева до одинаковой длины через ВЫБОР и ПОДСТРОКА либо преобразовать в числа.

Что делать, если в строке встречаются буквы или дефисы?

Преобразование через таблицу цифр даст NULL для таких значений — используйте это как фильтр некорректных данных. Если буквенная часть осмысленна (например, префикс серии), отделите её через ПОДСТРОКА и преобразуйте только числовую часть, либо нормализуйте данные обработкой до запроса.

Как преобразовать строку с дробным числом, например «12,5»?

В чистом запросе это практически не реализуемо разумными средствами: придётся отдельно разбирать целую и дробную части через ПОДСТРОКА и ПОДСТРОКА-поиск разделителя. Рациональный путь — выгрузить значения и преобразовать функцией Число() во встроенном языке, предварительно заменив запятую на точку при необходимости.

Почему сумма по преобразованному полю равна NULL или меньше ожидаемой?

Потому что хотя бы одно значение не преобразовалось и дало NULL, а агрегатные функции с NULL ведут себя неочевидно. Оберните выражение в ЕСТЬNULL(Выражение, 0) и отдельно проверьте запросом, сколько исходных значений содержат нецифровые символы или пробелы.

Что быстрее: таблица цифр в запросе или обход выборки с Число()?

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

Итог

Что важно запомнить

Прямого преобразования строки в число в запросе 1С нет: ВЫРАЗИТЬ для этого не подходит. Для сортировки и сравнения дополняйте строки нулями слева, для получения числа используйте таблицу цифр с ПОДСТРОКА или функцию Число() во встроенном языке. Всегда проверяйте данные на нецифровые символы, оборачивайте результат в ЕСТЬNULL, а при системной потребности заводите числовой реквизит в данных.