← Назад к вопросам

Какие SQL-функции работы с датами вы знаете? Приведите примеры.?

1.6 Junior🔥 241 комментариев
#SQL и базы данных

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Ответ: SQL-функции работы с датами

Основные функции для текущей даты и времени

NOW() / CURRENT_TIMESTAMP Возвращает текущую дату и время сервера.

SELECT NOW();  -- 2026-03-26 14:35:22.123456+00
SELECT CURRENT_TIMESTAMP;  -- То же самое
SELECT CURRENT_DATE;  -- 2026-03-26 (только дата)
SELECT CURRENT_TIME;  -- 14:35:22.123456 (только время)

CAST для типов дат

-- Преобразование строки в дату
SELECT CAST(2026-03-26 AS DATE);
SELECT CAST(2026-03-26 14:35:22 AS TIMESTAMP);

Функции для извлечения компонентов даты

EXTRACT() — получение отдельных частей даты

SELECT 
  EXTRACT(YEAR FROM created_at) AS year,
  EXTRACT(MONTH FROM created_at) AS month,
  EXTRACT(DAY FROM created_at) AS day,
  EXTRACT(HOUR FROM created_at) AS hour,
  EXTRACT(MINUTE FROM created_at) AS minute,
  EXTRACT(SECOND FROM created_at) AS second,
  EXTRACT(DOW FROM created_at) AS day_of_week,  -- 0=Sunday, 1=Monday
  EXTRACT(DOY FROM created_at) AS day_of_year
FROM events;

DATE_PART() — аналог EXTRACT (старый синтаксис)

SELECT DATE_PART(month, created_at) AS month;

Функции для округления и обрезания дат

DATE_TRUNC() — обрезка до указанного уровня

-- Очень полезно для группировки по периодам
SELECT 
  DATE_TRUNC(day, created_at)::DATE AS day,
  DATE_TRUNC(month, created_at)::DATE AS month,
  DATE_TRUNC(year, created_at)::DATE AS year,
  DATE_TRUNC(hour, created_at) AS hour
FROM events;

-- Пример: сколько событий в день
SELECT 
  DATE_TRUNC(day, created_at) AS event_day,
  COUNT(*) as event_count
FROM events
GROUP BY DATE_TRUNC(day, created_at)
ORDER BY event_day DESC;

Функции для арифметики с датами

INTERVAL — добавление/вычитание времени

-- Прибавить 7 дней
SELECT created_at + INTERVAL 7 days AS week_later;

-- Вычесть 30 дней
SELECT created_at - INTERVAL 30 days AS month_before;

-- Сложные интервалы
SELECT created_at + INTERVAL 1 year 2 months 3 days AS future_date;
SELECT created_at + INTERVAL 3 hours 30 minutes AS future_time;

AGE() — разница между двумя датами

-- Возраст пользователя
SELECT 
  user_id,
  DATE_OF_BIRTH,
  AGE(NOW(), DATE_OF_BIRTH) AS age
FROM users;

-- Как долго пользователь в системе
SELECT 
  user_id,
  created_at,
  AGE(NOW(), created_at) AS time_in_system
FROM users;

Прямая разница в днях/часах

-- Разница в днях
SELECT 
  order_id,
  (delivered_at - ordered_at)::int AS delivery_days
FROM orders;

-- Разница в часах
SELECT 
  session_id,
  EXTRACT(EPOCH FROM (end_time - start_time)) / 3600 AS session_duration_hours
FROM sessions;

Функции для форматирования дат

TO_CHAR() — преобразование даты в строку

SELECT 
  created_at,
  TO_CHAR(created_at, YYYY-MM-DD) AS formatted_date,
  TO_CHAR(created_at, DD.MM.YYYY HH24:MI:SS) AS russian_format,
  TO_CHAR(created_at, Mon DD, YYYY) AS english_format,
  TO_CHAR(created_at, Q) AS quarter
FROM events;

Форматы для разных локалей:

-- Американский
TO_CHAR(date, MM/DD/YYYY)  -- 03/26/2026

-- Европейский
TO_CHAR(date, DD/MM/YYYY)  -- 26/03/2026

-- ISO формат
TO_CHAR(date, YYYY-MM-DD)  -- 2026-03-26

-- С временем
TO_CHAR(date, YYYY-MM-DD HH24:MI:SS)  -- 2026-03-26 14:35:22

Функции для сравнения и фильтрации дат

BETWEEN для диапазона дат

-- События за последний месяц
SELECT * FROM events
WHERE created_at BETWEEN NOW() - INTERVAL 30 days AND NOW();

-- События в конкретный период
SELECT * FROM events
WHERE created_at BETWEEN 2026-01-01 AND 2026-03-31;

Проверка времени суток

SELECT * FROM events
WHERE EXTRACT(HOUR FROM created_at) >= 9 
  AND EXTRACT(HOUR FROM created_at) < 18;  -- Рабочие часы

Практические примеры для Product Analyst

Пример 1: DAU (Daily Active Users)

SELECT 
  DATE_TRUNC(day, last_activity)::DATE AS activity_date,
  COUNT(DISTINCT user_id) AS dau
FROM user_activities
WHERE last_activity >= NOW() - INTERVAL 90 days
GROUP BY DATE_TRUNC(day, last_activity)
ORDER BY activity_date DESC;

Пример 2: Когда пользователь стал активным впервые

SELECT 
  user_id,
  MIN(DATE_TRUNC(day, created_at))::DATE AS first_active_day,
  COUNT(*) AS total_events
FROM events
GROUP BY user_id;

Пример 3: Когорты по дате регистрации

SELECT 
  DATE_TRUNC(week, created_at)::DATE AS signup_week,
  COUNT(DISTINCT user_id) AS new_users,
  COUNT(DISTINCT CASE WHEN last_login >= created_at + INTERVAL 7 days 
                       THEN user_id END) AS week1_retention
FROM users
GROUP BY DATE_TRUNC(week, created_at)
ORDER BY signup_week DESC;

Практические советы

  • Всегда используй TIMESTAMPTZ в PostgreSQL для хранения дат (с timezone)
  • В WHERE условиях используй INDEX для DATE_TRUNC: CREATE INDEX ON events (DATE_TRUNC(day, created_at))
  • Для GROUP BY по датам лучше GROUP BY DATE_TRUNC, а не EXTRACT
  • INTERVAL полезен для динамических диапазонов дат
  • TO_CHAR лучше использовать только в SELECT для вывода, не в WHERE
  • Помни о timezone! Если пользователи в разных часовых поясах, это важно