Wyciąganie części daty: EXTRACT() i AGE()
Dzisiaj znowu zagłębimy się w manipulację danymi czasowymi, nauczymy się wyciągać z nich konkretne części (np. rok, miesiąc albo dzień tygodnia) za pomocą funkcji EXTRACT() i ogarniemy, jak liczyć wiek albo interwały czasowe między datami z funkcją AGE().
Praca z danymi czasowymi w realnych projektach często wymaga wyciągnięcia konkretnych części daty lub czasu. Na przykład:
- Podział zamówień według lat albo miesięcy;
- Zliczanie liczby użytkowników, którzy zarejestrowali się w konkretny dzień tygodnia;
- Analiza długości czasu między dwoma zdarzeniami.
Do takich zadań używamy funkcji EXTRACT() i AGE().
Co to jest EXTRACT()?
Funkcja EXTRACT() pozwala wyciągać konkretne części daty albo timestampu. Na przykład, możesz wyciągnąć rok z daty urodzenia, sprawdzić numer miesiąca albo nawet dzień tygodnia.
Składnia:
EXTRACT(part FROM source)
part: część daty, którą chcesz wyciągnąć. Może to byćYEAR,MONTH,DAY,HOUR,MINUTE,SECONDi inne.source: typ danych czasowych, z którego wyciągasz info. Może to być kolumna, stała albo wynik funkcji.
Przykład 1: wyciąganie roku, miesiąca i dnia
SELECT
EXTRACT(YEAR FROM '2024-11-15'::DATE) AS year_part,
EXTRACT(MONTH FROM '2024-11-15'::DATE) AS month_part,
EXTRACT(DAY FROM '2024-11-15'::DATE) AS day_part;
Wynik:
| year_part | month_part | day_part |
|---|---|---|
| 2024 | 11 | 15 |
Tutaj wyciągnęliśmy rok, miesiąc i dzień z daty 2024-11-15. Ten sposób jest przydatny, gdy chcesz grupować dane według konkretnych części daty.
Przykład 2: dzień tygodnia i godzina z czasu
SELECT
EXTRACT(DOW FROM '2024-11-15'::DATE) AS day_of_week,
EXTRACT(HOUR FROM '15:30:00'::TIME) AS hour_part;
Wynik:
| day_of_week | hour_part |
|---|---|
| 3 | 15 |
DOW(Day of Week) zwraca numer dnia tygodnia: niedziela —0, poniedziałek —1, itd.HOURwyciąga godziny z czasu.
Przykład 3: użycie na kolumnach
Jeśli mamy tabelę z datami, możemy wyciągać części dat do analizy. Załóżmy, że mamy tabelę orders:
| order_id | order_date |
|---|---|
| 1 | 2023-05-12 14:20 |
| 2 | 2023-06-18 10:45 |
| 3 | 2023-07-22 21:15 |
SELECT
order_id,
EXTRACT(MONTH FROM order_date) AS month,
EXTRACT(DAY FROM order_date) AS day
FROM orders;
Wynik:
| order_id | month | day |
|---|---|---|
| 1 | 5 | 12 |
| 2 | 6 | 18 |
| 3 | 7 | 22 |
Co to jest AGE()?
Funkcja AGE() służy do liczenia różnicy między dwoma timestampami. Na przykład, pozwala policzyć wiek klienta na podstawie jego daty urodzenia albo sprawdzić, ile czasu minęło od zamówienia.
Składnia:
AGE(timestamp1, timestamp2)
timestamp1: Późniejszy timestamp.timestamp2: Wcześniejszy timestamp.- Jeśli podasz tylko jeden parametr, PostgreSQL automatycznie porówna go z aktualną datą (
NOW()).
Przykład 1: liczenie wieku
SELECT AGE('2025-11-15'::DATE, '1990-05-12'::DATE) AS age;
Wynik:
| age |
|---|
| 35 years 6 mons |
Ten przykład pokazuje wiek osoby urodzonej 12 maja 1990 roku na dzień 15 listopada 2025 roku.
Przykład 2: interwał czasowy między zdarzeniami
SELECT AGE('2023-06-01 15:00'::TIMESTAMP, '2023-05-20 10:30'::TIMESTAMP) AS duration;
Wynik:
| duration |
|---|
| 11 days 4:30:00 |
Tutaj policzyliśmy interwał czasowy między dwoma zdarzeniami. Przydatne, gdy chcesz sprawdzić, ile czasu minęło między startem a zakończeniem zadania.
Przykład 3: wiek klienta
Załóżmy, że mamy tabelę customers:
| customer_id | birth_date |
|---|---|
| 1 | 1992-03-10 |
| 2 | 1985-07-07 |
Możemy policzyć wiek klientów:
SELECT
customer_id,
AGE(NOW(), birth_date) AS age
FROM customers;
Wynik na 13 czerwca 2025 roku:
| customer_id | age |
|---|---|
| 1 | 33 years 3 mons |
| 2 | 39 years 11 mons |
Oczywiście, u ciebie będzie inna wartość NOW() i inny wynik.
Praktyczne przykłady użycia EXTRACT() i AGE()
Teraz połączmy funkcje w realnych scenariuszach.
Przykład 1: grupowanie danych po miesiącach
Załóżmy, że mamy tabelę zamówień z datami. Żeby policzyć zamówienia po miesiącach, użyj takiego zapytania:
SELECT
EXTRACT(MONTH FROM order_date) AS order_month,
COUNT(*) AS total_orders
FROM orders
GROUP BY order_month
ORDER BY order_month;
Przykład 2: dni do końca ważności
Wyobraź sobie, że masz tabelę subscriptions:
| subscription_id | expiry_date |
|---|---|
| 1 | 2023-12-31 |
| 2 | 2024-05-15 |
Chcemy sprawdzić, ile dni zostało do końca subskrypcji:
SELECT
subscription_id,
AGE(expiry_date, NOW()) AS time_remaining
FROM subscriptions;
Wynik:
| subscription_id | time_remaining |
|---|---|
| 1 | 1 mons 15 days |
| 2 | 6 mons |
Typowe błędy i jak ich unikać
Przy używaniu EXTRACT() i AGE() początkujący czasem wpadają na miny:
- Próba wyciągnięcia niedozwolonej części, np. miesięcy z typu
TIME. Zapamiętaj: częściYEAR,MONTHiDAYdziałają zDATE,TIMESTAMP, ale nie zTIME. - Problemy z różnymi formatami danych czasowych. Na przykład, string
2023/11/15nie jest traktowany jako data. Używaj rzutowania typów z::DATEalboTO_DATE(). - Różnica między
AGE()a odejmowaniem timestampów. Jeśli chcesz dokładny interwał (w miesiącach, dniach, sekundach) — użyjAGE(), a do prostego liczenia dni wystarczą operacje arytmetyczne.
Teraz masz już wszystkie potrzebne skille, żeby wyciągać i analizować części danych czasowych w PostgreSQL. Spróbuj pobawić się EXTRACT() i AGE() w swoich projektach!
GO TO FULL VERSION