Тренування триває півтори години, робочий день — 8 годин, перерва — 20 хвилин, а варити яйця треба 10 хвилин. Все це — про часові інтервали.
Часові інтервали корисні в реальних додатках, коли треба, наприклад, розрахувати строки виконання задач, визначити різницю між двома датами або додавати/віднімати час. Але перш ніж зануритись у деталі, коротко згадаємо, на чому ми зупинились у попередніх лекціях.
У PostgreSQL INTERVAL — це спеціальний тип даних, призначений для представлення проміжків часу. На відміну від інших часових типів, він не зберігає конкретну дату чи час, а описує період, наприклад: "2 дні", "3 години", "5 хвилин".
Синтаксис INTERVAL
Інтервали можна задавати у форматі:
INTERVAL 'число одиниці_часу'
Приклади:
INTERVAL '2 days' -- Два дні
INTERVAL '3 hours' -- Три години
INTERVAL '15 minutes' -- П'ятнадцять хвилин
INTERVAL '1 day 2 hours' -- Один день і дві години
PostgreSQL підтримує різні одиниці часу: year, month, day, hour, minute, second. Ти можеш комбінувати їх в одному виразі.
Використання інтервалів у запитах
Тип даних INTERVAL стає особливо корисним, коли ти починаєш застосовувати його разом з іншими часовими типами (DATE, TIMESTAMP). Давай розглянемо основні операції.
Додавання інтервалу до дати/часу
Інтервали можна додавати до значень дати або часу. Наприклад:
SELECT CURRENT_DATE + INTERVAL '7 days' AS delivery_date;
-- Отримаємо дату через 7 днів від поточної
Результат:
| delivery_date |
|---|
| 2023-10-08 |
Віднімання інтервалів з дати/часу
Окрім додавання, можна і віднімати інтервали:
SELECT NOW() - INTERVAL '2 hours' AS two_hours_ago;
-- Отримаємо час дві години тому
Результат:
| two_hours_ago |
|---|
| 2023-10-01 10:00:00.000 |
Обчислення різниці між двома датами
Одна з потужних фішок INTERVAL — це розрахунок різниці між двома датами:
SELECT '2023-10-15'::DATE - '2023-10-01'::DATE AS days_difference;
-- Скільки днів між двома датами
Результат:
| days_difference |
|---|
| 14 days |
Зверни увагу, що результат у цьому випадку також представлений як часовий інтервал.
Практичні приклади роботи з INTERVAL
Розрахунок дати доставки. Уявімо інтернет-магазин, де доставка займає від 3 до 7 днів. Ось як можна розрахувати можливі дати доставки:
SELECT CURRENT_DATE + INTERVAL '3 days' AS earliest_delivery,
CURRENT_DATE + INTERVAL '7 days' AS latest_delivery;
Результат:
| earliest_delivery | latest_delivery |
|---|---|
| 2023-10-04 | 2023-10-08 |
Облік часу виконання задачі. Припустимо, є таблиця tasks, у якій для кожної задачі вказана дата початку. Треба розрахувати дату завершення задачі з урахуванням її тривалості у годинах:
CREATE TABLE tasks (
task_id SERIAL PRIMARY KEY,
task_name TEXT,
start_time TIMESTAMP,
duration INTERVAL
);
INSERT INTO tasks (task_name, start_time, duration)
VALUES
('Підготувати звіт', '2023-10-01 09:00:00', INTERVAL '4 hours'),
('Тестувати додаток', '2023-10-01 10:00:00', INTERVAL '2 hours 30 minutes');
SELECT task_name,
start_time,
start_time + duration AS end_time
FROM tasks;
Результат:
| task_name | start_time | end_time |
|---|---|---|
| Підготувати звіт | 2023-10-01 09:00:00 | 2023-10-01 13:00:00 |
| Тестувати додаток | 2023-10-01 10:00:00 | 2023-10-01 12:30:00 |
Порівняння строків виконання. Іноді треба знайти всі задачі, які виконались менше ніж за 3 години:
SELECT task_name
FROM tasks
WHERE duration < INTERVAL '3 hours';
Результат:
| task_name |
|---|
| Тестувати додаток |
Корисні трюки з інтервалами
Динамічне обчислення інтервалів. Можна комбінувати інтервали з іншими операціями. Наприклад, взяти кількість днів зі стовпця і перетворити це на інтервал:
SELECT CURRENT_DATE + (order_days || ' days')::INTERVAL AS order_due_date
FROM orders;
Приведення інтервалів до рядка. Іноді треба привести інтервал до рядка для відображення:
SELECT INTERVAL '2 days 3 hours'::TEXT AS interval_text;
Результат:
| interval_text |
|---|
| 2 days 03:00:00 |
Поширені помилки при роботі з INTERVAL
Робота з INTERVAL, незважаючи на його потужність, може викликати певні труднощі. Одна з типових помилок — використання неправильного формату. Наприклад, якщо спробувати INTERVAL '2 hours and 30 minutes', отримаєш помилку, бо PostgreSQL не розуміє слово "and". Правильний варіант: INTERVAL '2 hours 30 minutes'.
Ще одна помилка — забути вказати одиниці часу, як у INTERVAL '2'. PostgreSQL не розуміє, що це за "2", тому завжди явно вказуй одиниці (2 days, 2 hours).
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ