В практике разработки на платформе 1С:Предприятие часто возникают ситуации, когда данные в информационной базе хранятся в неоптимальном виде. Типичный пример — запись даты и времени события внутри строкового ресурса или комментария. Когда возникает задача построить отчет или сделать выборку за определенный период, разработчик сталкивается с серьезным ограничением: язык запросов 1С не умеет преобразовывать произвольную строку в тип Дата "на лету".
В этой статье мы подробно разберем, почему стандартный конструктор запросов не справляется с этой задачей напрямую, и проанализируем пять эффективных способов решения проблемы — от простых "хитростей" в запросе до правильного рефакторинга структуры базы данных.
Для начала выясним причину сложности. В SQL-системах существуют функции CAST или CONVERT, которые позволяют интерпретировать текст как дату. Однако в языке запросов 1С такие функции для типа Дата отсутствуют. Более того, вы не можете вызвать функцию общего модуля внутри запроса. Если поле Notes имеет тип Строка, то для системы это просто набор символов. Сравнение "01.01.2023" > "25.12.2022" с точки зрения строк вернет Ложь, так как символ "0" меньше символа "2", хотя хронологически первая дата позже второй.
Рассмотрим по шагам, как можно обойти эти ограничения.
Если формат записи в вашем регистре строго определен (например, дата всегда занимает первые 10 символов в виде ДД.ММ.ГГГГ), мы можем прибегнуть к технической хитрости. Мы преобразуем строку в формат ГГГГММДД прямо в запросе. Такой формат строк корректно сортируется и сравнивается по порядку.
Проанализируем ситуацию: нам нужно выделить год, месяц и день, а затем склеить их. В конструкторе запросов для этого используется функция ПОДСТРОКА.
Пример логики формирования условия в запросе:
ВЫБРАТЬ
Регистр.Notes КАК Заметка
ИЗ
РегистрСведений.СервернаяИнформация КАК Регистр
ГДЕ
ПОДСТРОКА(Регистр.Notes, 7, 4) +
ПОДСТРОКА(Регистр.Notes, 4, 2) +
ПОДСТРОКА(Регистр.Notes, 1, 2) МЕЖДУ "20230101" И "20231231"
Важные моменты этого метода:
ПОДСТРОКА(Notes, 7, 4).ПОДСТРОКА(Notes, 4, 2).ПОДСТРОКА(Notes, 1, 2).ГГГГММДД.Внимание: этот метод крайне медленный на больших объемах данных, так как СУБД не сможет использовать индексы и будет вынуждена сканировать всю таблицу целиком.
Если ваша задача — создать отчет, то возможности расширяются благодаря "Вычисляемым полям" в СКД. В отличие от чистого запроса, в выражении вычисляемого поля СКД можно использовать функции встроенного языка 1С.
Разберем алгоритм реализации:
ПолучитьДатуИзСтроки(ВходнаяСтрока). Она должна быть экспортной и находиться в модуле с флагом Сервер.xx.xx.xxxx/xx.xx.xx и возвращать реальный объект типа Дата.РеальнаяДата).ОбщийМодуль.ПолучитьДатуИзСтроки(Notes).Теперь в настройках отчета вы сможете использовать стандартный отбор по полю РеальнаяДата, выбирая периоды, кварталы или конкретные дни. Система сама применит преобразование при формировании результата.
Как справедливо отмечалось в обсуждении, хранение даты в строке — это архитектурная ошибка. Если информация о включении/выключении серверов важна для аналитики, ее нужно типизировать. Рассмотрим, как правильно изменить структуру регистра, не теряя текущие данные в поле Notes.
Рекомендуемые действия:
ДатаСобытия и типом Дата (состав даты: Дата и время).Notes и запишет полученные значения в новое поле ДатаСобытия.Для автоматизации заполнения в будущем, используйте обработчик события ПередЗаписью в модуле набора записей регистра:
Процедура ПередЗаписью(Отказ, Замещение)
Для Каждого Запись Из ЭтотОбъект Цикл
// Здесь вызываем вашу функцию парсинга
Запись.ДатаСобытия = ПарсингДатыИзТекста(Запись.Notes);
КонецЦикла;
КонецПроцедуры
Если данных в регистре немного (до 10-20 тысяч строк), и вы не можете менять структуру, можно воспользоваться программной обработкой результата запроса. Мы выберем все данные, обработаем их в коде и вернем в запрос через временную таблицу.
Посмотрим на пример реализации:
ВЫБРАТЬ Notes, Сервер ИЗ РегистрСведений.Серверы.ТаблицаЗначений.ДатаСобытия с типом Дата.Лев(), Сред() и Дата().МенеджерВременныхТаблиц.Этот метод позволяет гибко работать с данными, но требует осторожности при работе с памятью сервера приложений.
В редких случаях, когда поиск ведется по огромному массиву текстовых данных и важна скорость, можно задействовать Полнотекстовый поиск (ПП). Если для ресурса Notes включено индексирование полнотекстового поиска, вы можете искать фрагменты дат как текст. Однако этот метод не позволит задать строгий период "от и до" в понимании дат, он лишь поможет быстро найти строки, содержащие определенный год или месяц.
Выясним, какой метод выбрать именно вам:
Дата решит все проблемы с производительностью и корректностью выборок.Помните, что работа со строками в запросах — это всегда компромисс между удобством разработки и скоростью работы программы. Старайтесь хранить данные в тех типах, которые соответствуют их смыслу.