1с запрос преобразовать строку в число
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ПОДСТРОКА(Константы.Ц, Числа.Число_ / 10000000 + 1, 1) + ПОДСТРОКА(Константы.Ц, СЕКУНДА(ДОБАВИТЬКДАТЕ(Константы.О, СЕКУНДА, Числа.Число_ * 0.000006)) / 6 + 1, 1) + ПОДСТРОКА(Константы.Ц, СЕКУНДА(ДОБАВИТЬКДАТЕ(Константы.О, СЕКУНДА, Числа.Число_ * 0.00006)) / 6 + 1, 1) + ПОДСТРОКА(Константы.Ц, СЕКУНДА(ДОБАВИТЬКДАТЕ(Константы.О, СЕКУНДА, Числа.Число_ * 0.0006)) / 6 + 1, 1) + ПОДСТРОКА(Константы.Ц, СЕКУНДА(ДОБАВИТЬКДАТЕ(Константы.О, СЕКУНДА, Числа.Число_ * 0.006)) / 6 + 1, 1) + ПОДСТРОКА(Константы.Ц, СЕКУНДА(ДОБАВИТЬКДАТЕ(Константы.О, СЕКУНДА, Числа.Число_ * 0.06)) / 6 + 1, 1) + ПОДСТРОКА(Константы.Ц, СЕКУНДА(ДОБАВИТЬКДАТЕ(Константы.О, СЕКУНДА, Числа.Число_ * 0.6)) / 6 + 1, 1) + ПОДСТРОКА(Константы.Ц, СЕКУНДА(ДОБАВИТЬКДАТЕ(Константы.О, СЕКУНДА, Числа.Число_ * 6)) / 6 + 1, 1) + «.» + ПОДСТРОКА(Константы.Ц, СЕКУНДА(ДОБАВИТЬКДАТЕ(Константы.О, СЕКУНДА, Числа.Число_ * 60)) / 6 + 1, 1) + ПОДСТРОКА(Константы.Ц, СЕКУНДА(ДОБАВИТЬКДАТЕ(Константы.О, СЕКУНДА, Числа.Число_ * 600)) / 6 + 1, 1) + ПОДСТРОКА(Константы.Ц, СЕКУНДА(ДОБАВИТЬКДАТЕ(Константы.О, СЕКУНДА, Числа.Число_ * 6000)) / 6 + 1, 1) КАК Строка
ИЗ
(ВЫБРАТЬ
«0123456789» КАК Ц,
ДАТАВРЕМЯ(1, 1, 1) КАК О) КАК Константы,
Числа КАК Числа
1с предприятие 8.2 (8.2.15.289)
В табличной части документа есть поле с составным типом данных. Одним из типов является строка. Строка всегда имеет подобный вид «10.10.2012 — 10.10.2013», и даты могут быть различными.
Мне нужно в запросе каким-то образом выцепить вторую дату из строки (в данном случае «10.10.2013») и сравнить ее с параметром типа дата.
Как это можно сделать?
4 ответа 4
Начну издалека — сегодня я начал ненавидеть 1С еще сильнее.
А теперь по делу.
Два дня серфил, чтобы найти ответ на вопрос. В итоге получилась такая незамысловатая конструкция запроса:
Прошу заметить, что данный запрос учитывает только один год, только один месяц, и три последних дня. Значит надо добавить сюда over9000 строк кода, чтобы просматривались еще хотя бы несколько лет (с запасом), все 12 месяцев и 31 день.
А все потому что функция ДАТАВРЕМЯ не понимает в аргументах другие функции, а если бы и понимала, то в запросе нельзя представить строку датой, кроме как вышепредставленным онанизмом.
нельзя просто так взять и написать нормальный запрос
1С:Предприятие предоставляет возможность в запросах разыменовывать ссылочные поля, т.е. обращаться к подчиненным полям «через точку». Очень удобная возможность, которая позволяет упростить текст запроса. Но следует понимать каким образом в платформе реализован данный функционал и чем он опасен. Разберемся более подробно.
При обращении к подчиненному полю «через точку» происходит неявное соединение с таблицей этого типа. Например, обращение в запросе
ВЫБРАТЬ
ЗаказыКлиентовОстатки.Номенклатура.Артикул ,
ЗаказыКлиентовОстатки.ЗаказаноОстаток
ИЗ
РегистрНакопления.ЗаказыКлиентов.Остатки КАК ЗаказыКлиентовОстатки
Приведет к неявному соединению с таблицей справочника Номенклатура, а реальный запрос, который будет выполняться к базе будет аналогичен этому:
ВЫБРАТЬ
СпрНоменклатура.Артикул ,
ЗаказыКлиентовОстатки.ЗаказаноОстаток
ИЗ
РегистрНакопления.ЗаказыКлиентов.Остатки КАК ЗаказыКлиентовОстатки
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК СпрНоменклатура
ПО ЗаказыКлиентовОстатки.Номенклатура = СпрНоменклатура.Ссылка
На первый взгляд все корректно и правильно, но как система поведет себя, когда разыменовывается поле составного типа? Система будет соединяться СО ВСЕМИ таблицами, входящими в составной тип! Т.е. запрос
ВЫБРАТЬ
ЦеныНоменклатурыПоставщиков.Регистратор.Номер ,
ЦеныНоменклатурыПоставщиков.Цена
ИЗ
РегистрСведений.ЦеныНоменклатурыПоставщиков КАК ЦеныНоменклатурыПоставщиков
будет преобразован во что-то вроде:
И ко всей этой конструкции будут добавлены ограничения на уровне записей (RLS), если они используются. Все это может существенно замедлить выполнение запроса.
Иногда при написании запроса известно какая ссылка будет находиться в поле составного типа. В этом случае правильно привести составной тип к одному необходимому и избежать соединения со всеми таблицами составного типа. Для приведения составного типа к какому-то одному используется оператор
Выразить ( Выражение > КАК Тип значения >)
Параметр можно привести к ссылочному типу или к одному из примитивных типов.
Если содержит в составном типе требуемый , то приведение типа считается осуществимым, и для каждого значения указанного типа результатом будет это самое значение. Для значений других типов результатом приведения типа будет значение NULL.
Если не содержит в составном типе требуемый , то выполнение данного запроса завершится ошибкой.
Пример использования оператора Выразить, когда известно какая ссылка будет находиться в поле составного типа:
ВЫБРАТЬ
ВЫРАЗИТЬ (ЦеныНоменклатурыПоставщиков.Регистратор КАК Документ.ЗаказПоставщику).Номер КАК Номер,
ЦеныНоменклатурыПоставщиков.Цена
ИЗ
РегистрСведений.ЦеныНоменклатурыПоставщиков КАК ЦеныНоменклатурыПоставщиков
ГДЕ
ЦеныНоменклатурыПоставщиков.Регистратор ССЫЛКА Документ.ЗаказПоставщику
В запросе выше пожертвовали компактностью получения поля Номер ради производительности. В результате текст запроса получился более громоздким, но запрос выполнится быстрее за счет того, что не будет лишних ненужных соединений со всеми таблицами составного поля Регистратор.
Остались вопросы?
Спросите в комментариях к статье.
1. Преобразование таблицы строк в таблицу целых чисел.
Преобразование таблицы строк в таблицу целых чисел позволяет выполнить следующий пакетный запрос. При построении запроса считается, что максимальная длина числа ограничена 17 знаками.
"ВЫБРАТЬ Дано.НомерСтроки, Дано.Строка
|ПОМЕСТИТЬ Дано
|ИЗ &Дано КАК Дано
|;
|ВЫБРАТЬ 0 С, 1 КАК П
|ПОМЕСТИТЬ Р16
|ОБЪЕДИНИТЬ ВЫБРАТЬ 1, 10
|ОБЪЕДИНИТЬ ВЫБРАТЬ 2, 100
|ОБЪЕДИНИТЬ ВЫБРАТЬ 3, 1000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 4, 10000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 5, 100000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 6, 1000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 7, 10000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 8, 100000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 9, 1000000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 10, 10000000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 11, 100000000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 12, 1000000000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 13, 10000000000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 14, 100000000000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 15, 1000000000000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 16, 10000000000000000
|;
|ВЫБРАТЬ СУММА(А.П * Б.С) / МИНИМУМ(А.П) КАК Ответ
|ИЗ Дано, Р16 КАК А, Р16 КАК Б
|ГДЕ Б.С < 10 И ПОДСТРОКА(Дано.Строка, 17 - А.С, 1) = ПОДСТРОКА(""0123456789"", Б.С + 1, 1)
|СГРУППИРОВАТЬ ПО Дано.НомерСтроки"
В пакете всего три запроса.
Первый запрос пакета выполняет загрузку таблицы значений, содержащей исходные строковые представления чисел, и помещает ее в таблицу «Дано» с колонками «НомерСтроки» и "Строка". Второй запрос пакета формирует искусственную таблицу, содержащую номера позиций и их вес в десятичной позиционной системе счисления. Счет позиций идет справа налево.
Вся основная работа по преобразованию строки в число выполняется в последнем, третьем запросе пакета. В этом запросе таблица «Дано» умножается на таблицу весов позиций Р16 (КАК А) и еще раз на таблицу Р16 (КАК Б). В последней используется только первые десять строк первой колонки для прохода по номерам всех цифр строки «0123456789». Условие «ГДЕ» отбирает записи, в которых цифры в исходной строке и строке «0123456789» совпадают в позиции, определяемой для исходной строки строкой таблицы весов А и для строки цифр – строкой таблицы номеров цифр Б. Это дает возможность определить искомое число как сумму произведений веса позиции на номер цифры. При этом группировка идет по строкам таблицы «Дано».
Получающаяся сумма требует нормализации путем деления на минимальный вес позиции, имеющейся в числе. Это делается вместо отсчета позиций от реального правого края строки, который неизвестен в соответствующий момент.
Работа данного запроса иллюстрируется схемой на фиг.1, где показано преобразование в число строки «4957379257».
Нужно отметить, что данный алгоритм отличается высокой устойчивостью к ошибкам в исходных данных. Например, строка «123абракадабра», строка «абракадабра123», строка «так тоже123можно» одинаково хорошо преобразуются в число 123. Символы, не являющиеся цифрами, заменяются нулями или просто отбрасываются (если они справа от последней цифры) как не распознанные.
Преобразования в числа при задании различных исходных строк приведены на скриншотах, прилагаемых к статье.
2. Преобразование таблицы строк в таблицу дробных чисел.
Преобразование таблицы строк в таблицу дробных чисел можно выполнить следующим пакетным запросом.
"ВЫБРАТЬ Дано.НомерСтроки, Дано.Строка
|ПОМЕСТИТЬ Дано
|ИЗ &Дано КАК Дано
|;
|ВЫБРАТЬ 0 С, 1 КАК П
|ПОМЕСТИТЬ Р16
|ОБЪЕДИНИТЬ ВЫБРАТЬ 1, 10
|ОБЪЕДИНИТЬ ВЫБРАТЬ 2, 100
|ОБЪЕДИНИТЬ ВЫБРАТЬ 3, 1000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 4, 10000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 5, 100000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 6, 1000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 7, 10000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 8, 100000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 9, 1000000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 10, 10000000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 11, 100000000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 12, 1000000000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 13, 10000000000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 14, 100000000000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 15, 1000000000000000
|ОБЪЕДИНИТЬ ВЫБРАТЬ 16, 10000000000000000
|;
|ВЫБРАТЬ СУММА(А.П * Б.С * ВЫБОР КОГДА ПОДСТРОКА(Строка, 1, 17 - А.С) ПОДОБНО ""%.%"" ТОГДА 10 ИНАЧЕ 1 КОНЕЦ)
|/ МИНИМУМ(ВЫБОР КОГДА НЕ ПОДСТРОКА(Строка, 1, 17 - А.С) ПОДОБНО ""%.%"" ТОГДА А.П ИНАЧЕ 100000000000000000 КОНЕЦ) КАК Ответ
|ИЗ Дано КАК Дано, Р16 КАК А, Р16 КАК Б
|ГДЕ Б.С < 10 И ПОДСТРОКА(Строка, 17 - А.С, 1) = ПОДСТРОКА(""0123456789"", Б.С + 1, 1)
|СГРУППИРОВАТЬ ПО Дано.НомерСтроки"
Данный пакетный запрос отличается от предыдущего особой обработкой позиций, находящихся справа от первой десятичной точки. Такие позиции выделяются с использованием оператора ПОДОБНО. Проверяется подобие подстроки, заканчивающейся в данной позиции и шаблона "%.%". Для позиций, находящихся правее точки, применяется дополнительный множитель 10. Также меняется определение нормализующего делителя, который находится как минимум веса позиций, не находящихся правее первой точки.
3. Преобразование таблицы строк в таблицу целых чисел с "выращиванием" таблицы весов.
В данном варианте первого запроса вместо громоздкого текста, который непосредственно определяет строки таблицы весов, используется прием выращивания (порождения) этой таблицы.
"ВЫБРАТЬ Дано.НомерСтроки, Дано.Строка
|ПОМЕСТИТЬ Дано
|ИЗ &Дано КАК Дано
|;
|ВЫБРАТЬ 0 КАК С, 1 КАК П
|ПОМЕСТИТЬ Р1
|ОБЪЕДИНИТЬ ВЫБРАТЬ 1, 10
|;
|ВЫБРАТЬ А.С + Б.С КАК С, МАКСИМУМ(А.П * Б.П) КАК П
|ПОМЕСТИТЬ Р2
|ИЗ Р1 КАК А, Р1 КАК Б
|СГРУППИРОВАТЬ ПО А.С + Б.С
|;
|ВЫБРАТЬ А.С + Б.С КАК С, МАКСИМУМ(А.П * Б.П) КАК П
|ПОМЕСТИТЬ Р4
|ИЗ Р2 КАК А, Р2 КАК Б
|СГРУППИРОВАТЬ ПО А.С + Б.С
|;
|ВЫБРАТЬ А.С + Б.С КАК С, МАКСИМУМ(А.П * Б.П) КАК П
|ПОМЕСТИТЬ Р8
|ИЗ Р4 КАК А, Р4 КАК Б
|СГРУППИРОВАТЬ ПО А.С + Б.С
|;
|ВЫБРАТЬ А.С + Б.С КАК С, МАКСИМУМ(А.П * Б.П) КАК П
|ПОМЕСТИТЬ Р16
|ИЗ Р8 КАК А, Р8 КАК Б
|СГРУППИРОВАТЬ ПО А.С + Б.С
|;
|ВЫБРАТЬ СУММА(А.П * Б.С) / МИНИМУМ(А.П) КАК Ответ
|ИЗ Дано, Р16 КАК А, Р16 КАК Б
|ГДЕ Б.С < 10 И ПОДСТРОКА(Дано.Строка, 17 - А.С, 1) = ПОДСТРОКА(""0123456789"", Б.С + 1, 1)
|СГРУППИРОВАТЬ ПО Дано.НомерСтроки"
В этом пакетном запросе семь подзапросов.
Первый запрос, как всегда, осуществляет ввод данных.
4. Преобразование таблицы строк в таблицу дат.
Преобразование таблицы строк вида «ГГГГММДД» в таблицу дат можно выполнить следующим пакетным запросом.
"ВЫБРАТЬ Дано.НомерСтроки, Дано.Строка
|ПОМЕСТИТЬ Дано
|ИЗ &Дано КАК Дано
|;
|ВЫБРАТЬ 0 Х, 0 Д, 0 М, 1000 Г
|ПОМЕСТИТЬ Формат
|ОБЪЕДИНИТЬ ВЫБРАТЬ 1, 0, 0, 100
|ОБЪЕДИНИТЬ ВЫБРАТЬ 2, 0, 0, 10
|ОБЪЕДИНИТЬ ВЫБРАТЬ 3, 0, 0, 1
|ОБЪЕДИНИТЬ ВЫБРАТЬ 4, 0, 10, 0
|ОБЪЕДИНИТЬ ВЫБРАТЬ 5, 0, 1, 0
|ОБЪЕДИНИТЬ ВЫБРАТЬ 6, 10, 0, 0
|ОБЪЕДИНИТЬ ВЫБРАТЬ 7, 1, 0, 0
|ОБЪЕДИНИТЬ ВЫБРАТЬ 8, 0, 0, 0
|ОБЪЕДИНИТЬ ВЫБРАТЬ 9, 0, 0, 0
|;
|ВЫБРАТЬ ДОБАВИТЬКДАТЕ(ДОБАВИТЬКДАТЕ(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1,1,1,0,0,0),ДЕНЬ,СУММА(А.Д*Б.Х)-1),МЕСЯЦ,СУММА(А.М*Б.Х)-1),ГОД,СУММА(А.Г*Б.Х)-1) КАК Ответ
|ИЗ Дано, Формат КАК А, Формат КАК Б
|ГДЕ А.Х < 8 И Б.Х < 10 И ПОДСТРОКА(Дано.Строка, А.Х + 1, 1) = ПОДСТРОКА(""0123456789"", Б.Х + 1, 1)
|СГРУППИРОВАТЬ ПО Дано.НомерСтроки"
В данном запросе всего три подзапроса, причем первый из них выполняет функцию ввода таблицы строк в запрос.
Во втором запросе определяется временная таблица "Формат" с четырьмя колонками. В колонке "Х" записывается номер позиции в строке, начиная с нуля слева направо, в колонке "Д" - вес позиции при подсчете числа дней, "М" - месяцев, "Г" - лет. В последнем запросе вычисляется сумма произведений каждой колонки на номер цифры, находящейся в соответствующей позиции. Далее эти суммы произведений как число лет, месяцев и дней добавляются функцией добавить к дате сначала к "нулевому дню" '00010101', потом к результату первого добавления, а затем к результату второго. Это и дает в итоге искомую дату.
Очевидно, что переопределением таблицы "Формат" можно легко настроить запрос на нужный формат читаемых дат. Кроме того, нетрудно учесть наличие в строке значений часов, минут и секунд для ввода даты со временем.
5. Преобразование таблицы строк в таблицу дат с "выращиванием" таблицы позиций.
Текст данного запроса выглядит следующим образом.
"ВЫБРАТЬ Дано.НомерСтроки, Дано.Строка
|ПОМЕСТИТЬ Дано
|ИЗ &Дано КАК Дано
|;
|ВЫБРАТЬ 0 КАК Х
|ПОМЕСТИТЬ Р1
|ОБЪЕДИНИТЬ ВЫБРАТЬ 1
|;
|ВЫБРАТЬ А.Х + 2 * Б.Х КАК Х
|ПОМЕСТИТЬ Р2
|ИЗ Р1 КАК А, Р1 КАК Б
|;
|ВЫБРАТЬ А.Х + 4 * Б.Х КАК Х
|ПОМЕСТИТЬ Р4
|ИЗ Р2 КАК А, Р2 КАК Б
|;
|ВЫБРАТЬ ДОБАВИТЬКДАТЕ(
| ДОБАВИТЬКДАТЕ(
| ДОБАВИТЬКДАТЕ(
| ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0)
| , ДЕНЬ
| , СУММА(ВЫБОР А.Х КОГДА 7 ТОГДА 1 КОГДА 6 ТОГДА 10 КОНЕЦ * Б.Х) - 1
| )
| , МЕСЯЦ
| , СУММА(ВЫБОР А.Х КОГДА 5 ТОГДА 1 КОГДА 4 ТОГДА 10 КОНЕЦ * Б.Х) - 1
| )
| , ГОД
| , СУММА(ВЫБОР А.Х КОГДА 3 ТОГДА 1 КОГДА 2 ТОГДА 10 КОГДА 1 ТОГДА 100 КОГДА 0 ТОГДА 1000 КОНЕЦ * Б.Х) - 1
| ) КАК Ответ
|ИЗ Дано, Р4 КАК А, Р4 КАК Б
|ГДЕ А.Х < 8 И Б.Х < 10 И ПОДСТРОКА(Дано.Строка, А.Х + 1, 1) = ПОДСТРОКА(""0123456789"", Б.Х + 1, 1)
|СГРУППИРОВАТЬ ПО Дано.НомерСтроки"
Вся основная работа выполняется в пятом запросе. Год в виде числа, месяц в виде числа и день в виде числа получаются как сумма произведений номера цифры на вес позиции. Вес позиций определяется для каждого элемента даты отдельно при помощи оператора «ВЫБОР». Определенные год, месяц и день подставляются в функции «ДОБАВИТЬКДАТЕ», что и дает в итоге искомую дату.
6. Преобразование таблицы строк в таблицу дат со временем по формату, задаваемом параметром запроса.
При анализе запроса 4 можно увидеть, что формат даты задается таблицей весов позиций года, месяца и дня «Формат». Эту таблицу можно дополнить колонками для часов, минут и секунд. При различном заполнении этой таблицы можно анализировать даты, представленные в самом различном формате. Примеры заполнения таблицы "Формат" для различных форматов даты приведены на фиг.5.
В связи с эти возникает идея: А если вообще не задавать таблицу "Формат" заранее, а построить ее внутри запроса путем анализа текстового параметра "&Формат", передаваемого в запрос и определяющего формат даты. Тогда запрос станет чрезвычайно гибким и универсальным. На этой идее построен шестой запрос.
Текст данного запроса, отличающейся универсальностью за счет управления преобразованием с помощью строкового параметра "&Формат", можно посмотреть в прилагаемой к статье обработке. Дополнительным бонусом, скачавшим обработку, будут примеры очень уместного использования (как кажется) функции "НовыйЗапрос" [//infostart.ru/public/163853/] в модуле обработки. На скриншотах, прилагаемых к статье, приведены примеры преобразований при задании различных форматов даты. В определении формата использованы русские букы "Г", "М", "Д", "Ч", "Н" и "С". Важно, что позиции минут обозначены не маленькой русской "м", а русской "н", поскольку в запросе нет возможности различить регистр символов. Для заполнения незначащих позиций можно использовать любые другие символы. Примеры задания формата: "ГГГГММДДЧЧННСС", "ДД_ММ_ГГГГ_ЧЧ:НН:СС", "ССССС - тоже работает".
Заключение.
В заключение хочется отметить, что хотя язык запросов платформы 1С:Предприятие имеет весьма слабые возможности работы со строками, использование техники искусственых таблиц отчасти компенсирует этот недостаток. С другой стороны, та же причина открывает широкий простор нашей изобретательности при написании запросов. Пользуйтесь этим!
В языке запросов отсутствуют встроенные функции преобразования одних типов данных в другие, например, строк в числа или даты и наоборот. В работе «Выразить строку как число и строку как дату в запросе» были предложены достаточно компактные способы преобразований «из строки». Теперь дошла очередь до обратных к ним преобразований «в строку».
Основной проблемой рассматриваемого преобразования в строку является выделение каждого конкретного разряда исходного числа. Например, число 123 состоит из трех разрядов. Пусть разряды нумеруются справа налево, начиная с нуля. Разряды отличаются весом: нулевой разряд в десятичной позиционной системе счисления имеет вес 1, первый – 10, второй – 100 и так далее. Для выделения каждого разряда требуется найти целое от деления числа на вес разряда, а затем – остаток от деления полученного целого на 10. Первый (второй слева) разряд, таким образом, получится так: 123 разделим на 10, получим 12,3. Затем возьмем целое, получим 12. Затем найдем остаток от деления на 10, получим 2 – искомый первый (второй слева) разряд. Буквальная запись этих выражений в запросе получается очень и очень громоздкой, но существует другой путь.
Этот путь заключается в использовании для нахождения остатка от деления пары функций: СЕКУНДА и ДОБАВИТЬКДАТЕ. Дело в том, что функция СЕКУНДА фактически является функцией остатка от деления на 60 числа секунд, прошедшего с начала времен. Чтобы превратить ее в функцию расчета остатка от деления на 10 достаточно считать секунды шестерками. То есть требуемая функция будет записываться так:
Эта функция выделяет самый правый (нулевой) разряд числа Икс. Чтобы выделить первый разряд, нужно использовать функцию
А чтобы выделить второй – функцию
И так далее. Множитель 60 позволяет выделить разряд десятых долей, 600 – сотых и так далее.
Ограничением рассмотренного подхода является максимальное число секунд при работе с датами. Оно таково, что мы можем выделить не более 10-ти десятичных знаков в числе. Если число значащих знаков больше, исходное число потребуется предварительно разделить на две части «обычным» способом с использованием операции ВЫРАЗИТЬ КАК.
Приведем пример запроса для случая ЧИСЛО(10, 2)
Чтобы сделать запись чуть более короткой, две постоянные - цепочку цифр «0123456789» и начало времен можно вынести во вложенный запрос
Аналогичным образом можно преобразовать число в строку в двоичной системе счисления. Вот запрос для записи в виде строки восьми младших двоичных разрядов заданного числа:
Побочным следствием использованных закономерностей является то, что выражение
можно использовать в запросе для проверки четности числа Икс.
Для перевода даты в строку достаточно перевести в строку по отдельности число дней, месяцев и лет исходной даты. В итоге получается следующий запрос
Как видно, используемые для преобразования в строку выражения довольно просты и компактны, особенно если сравнить их с тем, что приходилось использовать до сих пор.
Встроенная функция запроса ВЫРАЗИТЬ() используется не только для приведения, но и для округления чисел.
Для этого используется такой синтаксис:
Общие особенности использования в запросе
Если в качестве параметра передано не числовое значение, это может не вызывать ошибки выполнения запроса, но значение корректно не обработается:
Например, если передан NULL или он сформировался при соединениях таблиц, значение на выходе останется NULL:
Передача же «Неопределено» вызывает ошибку «Несовместимые типы ВЫРАЗИТЬ»:
- Ссылочные типы или значения БУЛЕВО вызывают такую же ошибку (ИСТИНА не приводится к 1, а ЛОЖЬ к 0).
- ВЫРАЗИТЬ строку как число также нельзя, используя эту функцию.
Поэтому следует обрабатывать/проверять значение до его передачи в качестве параметра функции.
Обработка значения производится по методам округления (0.5 округляется до 1.0), поэтому, если требуется получить целое значение, то следует перед округлением вычесть 0.5 (половину цены шага)
Для округления до десятых в меньшую сторону вычесть 0.5, до сотых 0.05.
Демонстрация использования ВЫРАЗИТЬ в запросе для округления
ВЫБРАТЬ
1 . 56 КАК ЧислоПример ,
ВЫРАЗИТЬ ( 1 . 56 КАК ЧИСЛО ( 15 , 0 ) ) КАК ДоЦелого ,
ВЫРАЗИТЬ ( 1 . 56 — 0 . 5 КАК ЧИСЛО ( 15 , 0 ) ) КАК ДоЦелогоВниз ,
ВЫРАЗИТЬ ( 1 . 56 КАК ЧИСЛО ( 15 , 1 ) ) КАК ДоДесятых ,
ВЫРАЗИТЬ ( 1 . 56 — 0 . 05 КАК ЧИСЛО ( 15 , 1 ) ) КАК ДоДесятыхВниз ,
ВЫРАЗИТЬ ( 1 . 56 КАК ЧИСЛО ( 15 , 2 ) ) КАК ДоСотых
Реклама должна объяснить нам, без каких излишеств мы не можем прожить.
— Э.Макензи , 14 фраз
Данная конструкция в 1С используется в запросе для усечения длины строки,а также для приведения строки неограниченной длины к переменной строке с фиксированным ограничением.
Синтаксис функции
- Если на входе строка больше указанной длины — она усекается.
- Если меньше — остается неизменной.
- При передаче строки неограниченной длины происходит тоже самое.
Никаких пробелов в конце короткой строки не добавляется.
Другие особенности использования ВЫРАЗИТЬ КАК СТРОКА
Передача NULL в качестве параметра не вызывает ошибки, но на выходе будет NULL (не строкой).
Передача для преобразования других типов вызывает ошибку «Несовместимые типы ВЫРАЗИТЬ».
Преобразовать число как строку в запросе или же ссылку как строку в данной функции (да и в любых других функциях запроса невозможно). Это отличает TSQL запрос select cast(‘321’ as numeric(10) от запроса в 1С.
Функция ПРЕДСТАВЛЕНИЕ(ЧИСЛО), может на выходе запроса выдать строку, но внутри запроса ее результат использовать невозможно даже в качестве параметра для ВЫРАЗИТЬ.
Конкантенация (сложение) строк допустима и с результатом ВЫРАЗИТЬ:
«321»+ ВЫРАЗИТЬ («Строка» КАК СТРОКА(100))
Идентификатор ссылочного объекта в запросе получить невозможно и ожидаемое многими начинающими программистами 1С в КАЧЕСТВЕ ВЫРАЗИТЬ(ССЫЛКА как СТРОКА()) не работает: ни наименования, ни кода, ни идентификатора не получится — будет ошибка несовместимости типов.
Вот такая простая функция без особых сюрпризов.
Возможно когда-нибудь в платформе 8.4 1С исправит ситуацию с преобразованиями типов в запрос, а может тут дело в поддержании совместимости всех баз данных.
Как описываются машины в рекламных проспектах? “Волнующие”, “эффектные”, “изящные”, “грациозные”, “обтекаемой формы”. Прямо не знаешь, куда их вести — в гараж или в номер мотеля.
— Роберт Орбен
Читайте также: