Альтернативный вариант расчета возраста (лет, месяцев, дней) запросом
Появилась задача вычислить возраст человека на определенную дату. Сначала был написан вариант кодом, через цикл, но замер производительности показал, что подобное решение «тяжеловесное». Более того, я знаю, что задача будет повторяться, причем данные нужно будет выдавать запросом. Было решено сделать определенный шаблон, на основании которого можно было бы писать другие решения.
- Описание
- Подробнее
Описание
Сначала хорошим решением мне показались запросы в этой публикации. Но тестируя на разные случаи (29.02.2016 и 28.02.2017 и тому подобное) получал не совсем верные результаты. + мне сложно было вникнуть во всех хитросплетения и условия, поэтому решил написать свой вариант:
ВЫБРАТЬ
ГОД(&БольшаяДата) = ГОД(&МеньшаяДата) КАК ГодаРавны,
МЕСЯЦ(&БольшаяДата) > МЕСЯЦ(&МеньшаяДата) КАК МесяцБольше,
МЕСЯЦ(&БольшаяДата) = МЕСЯЦ(&МеньшаяДата) КАК МесяцыРавны,
ДЕНЬ(&БольшаяДата) > ДЕНЬ(&МеньшаяДата) КАК ДеньБольше,
ДЕНЬ(&БольшаяДата) = ДЕНЬ(&МеньшаяДата) КАК ДниРавны
ПОМЕСТИТЬ Условия
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Условия.ГодаРавны КАК ГодаРавны,
Условия.МесяцБольше КАК МесяцБольше,
Условия.МесяцыРавны КАК МесяцыРавны,
Условия.ДеньБольше КАК ДеньБольше,
Условия.ДниРавны КАК ДниРавны,
ДЕНЬ(КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&БольшаяДата, МЕСЯЦ, -1), МЕСЯЦ)) КАК ПоследнийДеньПредыдущегоМесяца,
ДЕНЬ(КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&БольшаяДата, МЕСЯЦ, -1), МЕСЯЦ)) < ДЕНЬ(&МеньшаяДата) И ДЕНЬ(&БольшаяДата) < 3 КАК ДеньПредыдущегоМесяцаМеньше,
Условия.ДеньБольше ИЛИ Условия.ДниРавны КАК ДеньБольшеИлиРавен,
Условия.МесяцБольше ИЛИ Условия.МесяцыРавны КАК МесяцБольшеИлиРавен,
Условия.ДеньБольше ИЛИ Условия.ДниРавны КАК ПоследнийМесяцПрошел,
Условия.МесяцБольше ИЛИ Условия.МесяцыРавны И (Условия.ДеньБольше ИЛИ Условия.ДниРавны) КАК ПоследнийГодПрошел
ПОМЕСТИТЬ СложныеУсловия
ИЗ
Условия КАК Условия
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВЫБОР
КОГДА СложныеУсловия.ГодаРавны
ТОГДА 0
КОГДА СложныеУсловия.ПоследнийГодПрошел
ТОГДА РАЗНОСТЬДАТ(&МеньшаяДата, &БольшаяДата, ГОД)
ИНАЧЕ РАЗНОСТЬДАТ(&МеньшаяДата, &БольшаяДата, ГОД) - 1
КОНЕЦ КАК Лет,
ВЫБОР
КОГДА СложныеУсловия.ПоследнийМесяцПрошел И СложныеУсловия.МесяцБольшеИлиРавен
ТОГДА МЕСЯЦ(&БольшаяДата) - МЕСЯЦ(&МеньшаяДата)
КОГДА СложныеУсловия.МесяцБольше
ТОГДА МЕСЯЦ(&БольшаяДата) - МЕСЯЦ(&МеньшаяДата) - 1
КОГДА СложныеУсловия.ПоследнийМесяцПрошел
ТОГДА 12 - (МЕСЯЦ(&МеньшаяДата) - МЕСЯЦ(&БольшаяДата))
ИНАЧЕ 12 - (МЕСЯЦ(&МеньшаяДата) - МЕСЯЦ(&БольшаяДата) + 1)
КОНЕЦ КАК Месяцев,
ВЫБОР
КОГДА СложныеУсловия.МесяцБольшеИлиРавен И СложныеУсловия.ДеньБольшеИлиРавен
ТОГДА ДЕНЬ(&БольшаяДата) - ДЕНЬ(&МеньшаяДата)
КОГДА СложныеУсловия.ПоследнийМесяцПрошел И СложныеУсловия.ДеньБольшеИлиРавен
ТОГДА ДЕНЬ(&БольшаяДата) - ДЕНЬ(&МеньшаяДата)
КОГДА СложныеУсловия.ДеньПредыдущегоМесяцаМеньше ТОГДА 0
ИНАЧЕ СложныеУсловия.ПоследнийДеньПредыдущегоМесяца - (ДЕНЬ(&МеньшаяДата) - ДЕНЬ(&БольшаяДата))
КОНЕЦ КАК Дней
ИЗ
СложныеУсловия КАК СложныеУсловияВозможно такой вариант кому-то покажется очевиднее и понятнее. Тестировались различные вариации дат. При этом здесь есть следующее допущение: БольшаяДата всегда больше.
Сверялся с этим онлайн калькулятором, но если кто-то найдет ошибку — жду в комментарии!
