При разработке отчетов или систем оповещения в 1С часто возникает задача: выбрать сотрудников, чей день рождения или юбилей наступает в ближайшее время. Эта задача кажется простой, но требует внимательного подхода к работе с датами, так как мы должны игнорировать год рождения, фокусируясь только на дне и месяце.
Основная сложность заключается в том, что поле ДатаРождения содержит год. Если мы будем сравнивать его напрямую, запрос вернет данные только для тех, кто родился в конкретном году. Для решения этой проблемы мы приведем дату рождения к текущему году.
Рассмотрим вариант запроса, который позволяет найти сотрудников, чей день рождения попадает в интервал 30 дней от текущей даты:
ВЫБРАТЬ
Сотрудники.Ссылка КАК Ссылка,
Сотрудники.ДатаРождения КАК ДатаРождения
ИЗ
Справочник.Сотрудники КАК Сотрудники
ГДЕ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&ТекДата, ГОД), ДЕНЬ,
РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(Сотрудники.ДатаРождения, ГОД), Сотрудники.ДатаРождения, ДЕНЬ))
МЕЖДУ &ТекДата И ДОБАВИТЬКДАТЕ(&ТекДата, ДЕНЬ, 30)
В этом примере мы используем функцию РАЗНОСТЬДАТ, чтобы вычислить порядковый номер дня в году для даты рождения, а затем прибавляем это количество дней к НАЧАЛОПЕРИОДА текущего года. Это позволяет нам эффективно «перенести» дату рождения на текущий год и провести корректное сравнение в рамках интервала.
Юбилей — это особый день рождения, когда человеку исполняется количество лет, кратное 10 (30, 40, 50 и т.д.). Для поиска таких сотрудников мы можем расширить условие запроса, добавив проверку возраста.
Рассмотрим подход, объединяющий поиск по периоду и проверку кратности возраста 10 годам:
ВЫБРАТЬ
Сотрудники.Ссылка КАК Ссылка,
Сотрудники.ДатаРождения КАК ДатаРождения
ИЗ
Справочник.Сотрудники КАК Сотрудники
ГДЕ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&ТекДата, ГОД), ДЕНЬ,
РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(Сотрудники.ДатаРождения, ГОД), Сотрудники.ДатаРождения, ДЕНЬ))
МЕЖДУ &ТекДата И ДОБАВИТЬКДАТЕ(&ТекДата, ДЕНЬ, 30)
И (ГОД(&ТекДата) - ГОД(Сотрудники.ДатаРождения)) / 10 =
(ВЫРАЗИТЬ((ГОД(&ТекДата) - ГОД(Сотрудники.ДатаРождения)) / 10 КАК ЧИСЛО(10, 0)))
Здесь мы используем математическое деление для проверки кратности. Если возраст, деленный на 10, равен целому числу, значит, текущий год для сотрудника является юбилейным.
ИЛИ в запросах может замедлить их выполнение на больших объемах данных. Старайтесь вычислять даты начала и окончания периода в коде 1С, а в запрос передавать уже готовые параметры &ДатаНачала и &ДатаОкончания.Работая с подобными задачами, всегда анализируйте, насколько архитектура вашего решения устойчива к изменениям требований бизнеса. Помните, что чистота кода и его легкость в поддержке важнее, чем попытка уместить всю логику в один громоздкий запрос.