Как отсортировать сотрудников по юбилеям и рассчитать точный возраст в запросе 1С?

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом IT и автоматизация бизнеса
← На главную

При разработке кадровых отчетов часто возникает необходимость выделить сотрудников, у которых в текущем году намечается юбилей — возраст, кратный 5 (25, 30, 35 лет и так далее). Отдел кадров может потребовать, чтобы такие «юбиляры» выводились в самом начале списка. Давайте рассмотрим, с какими подводными камнями можно столкнуться при решении этой задачи исключительно средствами языка запросов 1С, и разберем эффективные способы ее реализации.

Проблема вычисления остатка от деления в запросе 1С

В коде модулей 1С мы привыкли использовать оператор % для получения остатка от деления (например, Возраст % 5 = 0). Однако язык запросов 1С не поддерживает данный оператор. Нам приходится искать обходные пути. Проанализируем несколько рабочих вариантов проверки на кратность прямо в тексте запроса.

Вариант 1: Использование функции ВЫРАЗИТЬ

Самый популярный способ, который часто предлагают разработчики, основан на приведении типов. Мы делим возраст на 5, отбрасываем дробную часть с помощью функции ВЫРАЗИТЬ и сравниваем с результатом обычного деления. Если они равны, значит число делится без остатка.


ВЫБОР 
    КОГДА ВЫРАЗИТЬ(Таб.Возраст / 5 КАК ЧИСЛО(10, 0)) = (Таб.Возраст / 5)
        ТОГДА ИСТИНА
    ИНАЧЕ ЛОЖЬ
КОНЕЦ КАК Юбилей

Вариант 2: Надежная математическая формула

Второй паттерн учитывает правила математического округления 1С. Чтобы гарантированно получить остаток от деления в запросе, мы можем вычесть 0.5 перед округлением:


ВЫБОР
    КОГДА Возраст - 5 * ВЫРАЗИТЬ((Возраст / 5) - 0.5 КАК ЧИСЛО(15, 0)) = 0
        ТОГДА 1
    ИНАЧЕ 0
КОНЕЦ КАК ПолеСортировки

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

Как правильно считать возраст сотрудника: разбор ошибки РАЗНОСТЬДАТ

Рассмотрим еще один критически важный аспект. Часто для вычисления возраста используют простую конструкцию:

РАЗНОСТЬДАТ(ФизическоеЛицо.ДатаРождения, &ТекущаяДата, ГОД) КАК Возраст

Эта функция математически «грубая». Она вычитает только годы, игнорируя месяц и день. Например, если сотрудник родился 31 декабря, а отчет формируется 1 января следующего года, функция прибавит ему целый год, хотя фактически прошел только один день. Выясним, как написать условие правильно.

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


РАЗНОСТЬДАТ(ДатаРождения, &ТекущаяДата, ГОД) - 
ВЫБОР 
    КОГДА (МЕСЯЦ(ДатаРождения) > МЕСЯЦ(&ТекущаяДата)) 
    ИЛИ (МЕСЯЦ(ДатаРождения) = МЕСЯЦ(&ТекущаяДата) И ДЕНЬ(ДатаРождения) > ДЕНЬ(&ТекущаяДата)) 
        ТОГДА 1 
    ИНАЧЕ 0 
КОНЕЦ КАК ТочныйВозраст

Ошибка: Неверные параметры "РАЗНОСТЬДАТ"

При усложнении запроса можно столкнуться с ошибкой выполнения. Проанализируем типичную ситуацию:


{(68, 31)}: Неверные параметры "РАЗНОСТЬДАТ"
КОГДА (ВЫРАЗИТЬ(РАЗНОСТЬДАТ(<<?>>ВТДанные.Возраст, &ТекущаяДата, ГОД) / 5 КАК ЧИСЛО(10, 0))) = РАЗНОСТЬДАТ(ВТДанные.Возраст, &ТекущаяДата, ГОД) / 5

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

Альтернативные и оптимальные подходы к решению

Перегружать текст запроса сложными вычислениями не всегда целесообразно. Давайте посмотрим, какие еще инструменты нам доступны.

  1. Обработка результата после запроса. Как отметил автор обсуждаемой проблемы, можно выгрузить результат запроса в таблицу значений и рассчитать кратность уже средствами встроенного языка:
    
    СколькоЛет = Цел(Год(ТекущаяДата()) - Год(ТаблицаДанных.ДатаРождения));
    Если (СколькоЛет % 5) = 0 Тогда
        // Обработка юбиляра
    КонецЕсли;
    
  2. Система Компоновки Данных (СКД). Это наиболее современный и рекомендуемый 1С подход. В запросе вы получаете только саму дату рождения. Далее в «Вычисляемых полях» СКД вы можете использовать язык выражений СКД или вызвать экспортную функцию общего модуля, которая вернет признак юбилея. Это сделает сам запрос легким и легко читаемым, а бизнес-логику расчета оставит там, где ей и место.

Используя эти методы, вы сможете точно вычислять возраст сотрудников, корректно определять юбиляров и безошибочно сортировать данные в любых кадровых отчетах 1С.

← На главную