Короткий ответ
В PostgreSQL можно использовать EXTRACT(YEAR FROM AGE(CURRENT_DATE, birth_date)), где AGE возвращает интервал между двумя датами, а EXTRACT(YEAR FROM ...) берёт из него количество полных лет с учётом того, был ли уже день рождения в этом году.
Как это работает подробнее
AGE(end_date, start_date) в PostgreSQL корректно учитывает календарные месяцы и дни, а не просто делит разницу в днях на 365 — поэтому результат точнее для расчёта «полных лет». Простое вычисление (CURRENT_DATE - birth_date) / 365 даёт приблизительный и иногда неверный на один год результат из-за високосных лет.
Пример кода
question-32.sql
SELECT customer_id, EXTRACT(YEAR FROM AGE(CURRENT_DATE, birth_date)) AS age
FROM customers;Что использовать на практике
- для возрастной сегментации важно явно зафиксировать точку отсчёта — «на сегодня» (
CURRENT_DATE) или «на момент события» (например, на дату заказа), особенно если отчёт строится не в реальном времени, а на исторических данных. Дляbirth_date = '2000-05-01'и текущей даты2024-04-20результат — 23 (день рождения ещё не наступил). Проверка: вручную посчитать возраст для нескольких граничных дат рождения (сегодня, вчера, завтра относительно текущей даты минус N лет).
Подводные камни
- делят разницу в днях на 365 без учёта високосных годов и месяцев, что на границе дня рождения может показать на единицу неверный возраст; считают возраст от
CURRENT_DATE, когда в контексте отчёта нужен возраст на момент конкретного события в прошлом.