Во встроенном языке запросов 1С не реализована функция определения длины строки. В тех случаях, когда длину строки необходимо определять именно в запросе, приходится прибегать к различным ухищрениям. Как вариант, предлагается использовать быстрый метод половинного деления.
Скачать файл
ВНИМАНИЕ:
Файлы из Базы знаний - это исходный код разработки.
Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы.
Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных.
Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.
Здесь описан другой способ (21. Определение длины строки в запросе).
Необходимо построить в запросе дерево поиска конца строки. Для формирования текста с деревом, включаемого в запрос, используется рекурсивная функция:
Функция Дерево(Реквизит, Начало, Конец) Экспорт
Если Начало + 1 = Конец Тогда
Возврат Строка(Конец);
КонецЕсли;
Середина = Начало + Цел((Конец - Начало) / 2);
СтрокаДерево = "ВЫБОР КОГДА ПОДСТРОКА(" + Реквизит + ", " + (Середина + 1) + ", 3) = """" ТОГДА "
+ Дерево(Реквизит, Начало, Середина) + " ИНАЧЕ " + Дерево(Реквизит, Середина, Конец) + " КОНЕЦ";
Возврат СтрокаДерево;
КонецФункции // Дерево()
Где:
Реквизит – строка с именем таблицы и реквизита, содержащего определяемые строки.
Начало, Конец – интервал в котором будет производится поиск конца строки.
ТекстДерево = Дерево("Строки.Строка", -1, 300);
Недостатком данного способа является необходимость заранее определиться с максимальной длиной строки, а если длина строк окажется больше, то длина будет определена как максимальная. С увеличением максимальной длины строки увеличивается длина текста запроса и вложенность операторов выбора, поэтому нужно ограничиваться разумными величинами.
Вставляем полученное дерево в запрос:
Запрос.Текст =
"ВЫБРАТЬ
| Строки.Строка,
| " + ТекстДерево + " КАК Длина
|ИЗ
| Строки КАК Строки
|
|УПОРЯДОЧИТЬ ПО
| Длина УБЫВ";
Данный инструмент помогает анализировать доработанную конфигурацию после обновления на новый релиз и находить «битые» тексты запросов, в которых участвуют несуществующие в новом релизе метаданные.
Столкнулся с интересной ситуацией, которую хотел бы разобрать, ввиду её неочевидности. Речь пойдёт про использование функции запроса АВТОНОМЕРЗАПИСИ() и проблемы, которые могут возникнуть.
Работая с типовыми отчетами в конфигурациях «Зарплата и управление персоналом, редакция 3», «Зарплата и кадры государственного учреждения, редакция 3» и подобных, в схемах компоновки данных можно встретить конструкции запросов, которые обращаются к некоторым виртуальным таблицам.
Отлаживая взаимодействие с базой данных, мы регулярно сталкиваемся с зависающими или подозрительно долго выполняющимися обращениями, негативно влияющими на производительность. О том, как в PostgreSQL выявить подозрительные запросы, основываясь на доступной о них информации, расскажем в статье.
Вот гораздо более компактная реализация той же самой идеи:
ВЫБРАТЬ
"12345678901234567890123456789012345678901234567890" КАК Стр,
1023 КАК Х
ПОМЕСТИТЬ Дано
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Стр, Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 0, 1) = "" ТОГДА Х - 1 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 1, 1) = "" ТОГДА Х - 2 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 3, 1) = "" ТОГДА Х - 4 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 7, 1) = "" ТОГДА Х - 8 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 15, 1) = "" ТОГДА Х - 16 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 31, 1) = "" ТОГДА Х - 32 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 63, 1) = "" ТОГДА Х - 64 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 127, 1) = "" ТОГДА Х - 128 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 255, 1) = "" ТОГДА Х - 256 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 511, 1) = "" ТОГДА Х - 512 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ Дано КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ
Показать
Этим запросом можно получить длину строки до 1023 быстро и без дополнительных таблиц.
(5) ildarovich, Супер! Возьму на вооружение в новой обработке. Переносите способ в Ваш пост про минимализмы. Длину подстроки, однако, следует брать 3 символа, иначе пробел дает ложный конец строки, например, после 31 символа.
(6) чтобы "отловить" любое количество внутренних пробелов, идущих подряд, длина подстроки должна быть достаточной, чтобы "дотянуться" до конца строки. Не вникая особо, можно везде поставить 1024. А хвостовые пробелы вообще не ловятся.
(13) Странно под пятницу 13-е тринадцатое сообщение спряталось у меня в середину списка комментариев, поэтому не сразу его нашел, так как смотрел в конце ленты.
По сути вопроса:
Проверил на 8.3.11. У меня не подтверждается, пробелы в середине не учитываются, вот скриншот. Возможно, просто Х не задаете. Попробуйте в консоли точно такой запрос как в (5).
Проверил на 8.3.11. У меня не подтверждается, пробелы в середине не учитываются, вот скриншот.
Короче, проблема возникает, если в конце строки через пробел добавляется одиночные символы, но как-то странно вообще (см. картинки):
Строка "1234567890123456789012345678901234567890123456789 1 2 3 ff zz zz" показывает 64, что правильно, но стоит только вместо "ff" указать "f" - и все! Дальше как пойдет - поведение системы непредсказуемо...
ВЫБРАТЬ
"1234567890123456789012345678901234567890123456789 1 2 3 f zz zz" КАК Стр,
1023 КАК Х
ПОМЕСТИТЬ Дано
;
ВЫБРАТЬ
Стр, Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 0, 1) + "!" = "!" ТОГДА Х - 1 ИНАЧЕ Х КОНЕЦ Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 1, 1) + "!" = "!" ТОГДА Х - 2 ИНАЧЕ Х КОНЕЦ Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 3, 1) + "!" = "!" ТОГДА Х - 4 ИНАЧЕ Х КОНЕЦ Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 7, 1) + "!" = "!" ТОГДА Х - 8 ИНАЧЕ Х КОНЕЦ Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 15, 1) + "!" = "!" ТОГДА Х - 16 ИНАЧЕ Х КОНЕЦ Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 31, 1) + "!" = "!" ТОГДА Х - 32 ИНАЧЕ Х КОНЕЦ Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 63, 1) + "!" = "!" ТОГДА Х - 64 ИНАЧЕ Х КОНЕЦ Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 127, 1) + "!" = "!" ТОГДА Х - 128 ИНАЧЕ Х КОНЕЦ Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 255, 1) + "!" = "!" ТОГДА Х - 256 ИНАЧЕ Х КОНЕЦ Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 511, 1) + "!" = "!" ТОГДА Х - 512 ИНАЧЕ Х КОНЕЦ Х
ИЗ Дано КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ
Показать
Хотя, наверное, можно и вот так:
ВЫБРАТЬ
"1234567890 " КАК Стр,
1023 КАК Х
ПОМЕСТИТЬ Дано
;
ВЫБРАТЬ
Стр, Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 0, 512) = "" ТОГДА Х - 1 ИНАЧЕ Х КОНЕЦ Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 1, 512) = "" ТОГДА Х - 2 ИНАЧЕ Х КОНЕЦ Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 3, 512) = "" ТОГДА Х - 4 ИНАЧЕ Х КОНЕЦ Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 7, 512) = "" ТОГДА Х - 8 ИНАЧЕ Х КОНЕЦ Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 15, 512) = "" ТОГДА Х - 16 ИНАЧЕ Х КОНЕЦ Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 31, 512) = "" ТОГДА Х - 32 ИНАЧЕ Х КОНЕЦ Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 63, 512) = "" ТОГДА Х - 64 ИНАЧЕ Х КОНЕЦ Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 127, 512) = "" ТОГДА Х - 128 ИНАЧЕ Х КОНЕЦ Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 255, 512) = "" ТОГДА Х - 256 ИНАЧЕ Х КОНЕЦ Х
ИЗ (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 511, 512) = "" ТОГДА Х - 512 ИНАЧЕ Х КОНЕЦ Х
ИЗ Дано КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ
Показать
Разница в реакции на хвостовые пробелы. В первом варианте они считаются в длине строки, а во втором случае - нет.
Большое спасибо за внимательность. Очередная "последняя" обнаруженная ошибка, которая, как известно, всегда предпоследняя.
Нужно будет еще в минимализмах поправить.
(17) я сравнивал обрезанную и необрезанную строку, чтобы решить подобную проблему, хотя, конечно, смысла особого в получении длины строки таким образом нет (на мой скромный взгляд). Но как упражнение весьма интересно.
(18) Да, больше как упражнение (во всяком случае, не помню, чтобы самому приходилось на практике применять). Тем более, кто-то писал (сам не проверил еще), что в Postgre есть более жесткое ограничение на максимальный уровень вложенности. С другой стороны, для небольших строк это лучше чем гребенка "подобно" или соединение с искусственной таблицей. Поэтому пусть будет как возможный вариант.
Интересненько, любопытненько... Хотя не ясно как эти две статьи связать.
ЗЫ: и сразу полезли мысли (про нечеткий поиск) "где такое можно применить, внедрить в решение, продать наконец. )))
Нигде, никого это не заинтересует. Как и отсутствие дублей...
Если только вы не программист на предприятии и вам эти косяки исправлять.
(12) способ определения длины строки в запросе применил при определении схожести строк в нечетком поиске. По поводу применить/продать - автоматизировать что-то таким способом нельзя, нужно пользоваться очень осторожно и перепроверять результаты.