Date e orari non sono solo numeri astratti, ma la chiave per una parte preziosa delle informazioni nei dati. Nella vita reale ti imbatti spesso nelle date: ad esempio, analisi delle vendite per mese, filtraggio per data di nascita dei dipendenti o confronto di intervalli temporali. Sapere come gestire le date ti permette di scrivere query più flessibili e fare analisi più complesse.
Esempi dove lavorare con le date è fondamentale:
- Analisi delle vendite per un mese specifico.
- Conteggio degli utenti registrati nell'ultimo anno.
- Creazione di report su intervalli di tempo (tipo entrate mensili).
In PostgreSQL ci sono un sacco di funzioni per lavorare con le date, e ora vediamo solo le più utili.
Funzioni base per lavorare con date e orari
La funzione NOW() restituisce la data e l'orario attuali del server del database. Si usa quando vuoi sapere l'orario preciso in questo momento. Un esempio: vuoi salvare l'orario di creazione di un nuovo record.
SELECT NOW();
Esempio di risultato:
2023-11-05 15:23:45.123456+00
Esempio di utilizzo: Vuoi inserire un ordine con la data e l'orario attuali:
INSERT INTO orders (order_id, order_date, total_amount)
VALUES (1, NOW(), 150.00);
Commento: qui
NOW() aggiunge automaticamente la data e l'orario attuali nella colonna
order_date.
Come funziona esattamente l'operatore INSERT lo scoprirai nelle prossime lezioni :P
Funzione CURRENT_DATE
Se ti serve solo la data attuale senza l'orario, usa CURRENT_DATE. Restituisce solo anno, mese e giorno.
Sintassi:
SELECT CURRENT_DATE;
Esempio di risultato:
2023-11-05
Esempio di utilizzo: Supponiamo che vuoi ottenere i record per la giornata di oggi:
SELECT *
FROM orders
WHERE order_date = CURRENT_DATE;
Commento: qui confrontiamo la data nella colonna
order_date con la data attuale.
Aggiungiamo un po' di umorismo. NOW() è come il tuo caffè al lavoro: pronto subito. E CURRENT_DATE è come il calendario appeso al muro: solo la data, senza dettagli extra.
Estrarre parti della data con DATE_PART()
La funzione DATE_PART() ti permette di ottenere una parte specifica della data, tipo anno, mese, giorno, ora o minuto. È comodo, ad esempio, per contare gli ordini di un certo anno o trovare il giorno della settimana.
Sintassi:
DATE_PART('parte', data)
Esempio:
SELECT DATE_PART('year', NOW()) AS current_year;
Esempio di risultato:
| current_year |
|---|
| 2025 |
Parti della data che puoi estrarre:
year: anno.month: mese.day: giorno.hour: ora.minute: minuto.second: secondo.dow: giorno della settimana (0 = domenica).
Esempio 2: Estraiamo il mese dalla data attuale.
SELECT DATE_PART('month', CURRENT_DATE) AS current_month;
Risultato:
| current_month |
|---|
| 6 |
Puoi usare DATE_PART() anche per calcoli più complessi. Ad esempio:
Vuoi selezionare solo gli utenti nati quest'anno:
SELECT *
FROM students
WHERE DATE_PART('year', birth_date) = DATE_PART('year', CURRENT_DATE);
Esempio di risultato:
| id | first_name | last_name | birth_date | grade |
|---|---|---|---|---|
| 1 | Otto | Art | 2025-03-12 | 9 |
| 2 | Anna | Pal | 2025-07-08 | 8 |
| 3 | Piu | Wolf | 2025-01-22 | 10 |
| 4 | Eva | Go | 2025-09-30 | 7 |
| 5 | Dan | Sok | 2025-06-14 | 9 |
Esempi pratici
In alcuni esempi ci saranno operatori che ancora non conosci. Non preoccuparti, presto li userai come se niente fosse. Voglio solo mostrarti più casi reali possibili. E anche incuriosirti un po' :)
Esempio 1: Calcolare l'età dell'utente
Supponiamo di avere una tabella users con la data di nascita di ogni utente. Vogliamo calcolare la loro età.
Query:
SELECT user_id, first_name, last_name,
DATE_PART('year', CURRENT_DATE) - DATE_PART('year', birth_date) AS age
FROM users;
Semplicemente sottraiamo gli anni della data attuale e della data di nascita. È un modo veloce, ma non precisissimo per ottenere l'età.
Esempio di risultato:
| user_id | first_name | last_name | age |
|---|---|---|---|
| 101 | Alex | Lin | 25 |
| 102 | Maria | Chi | 30 |
| 103 | Tor | Coz | 22 |
| 104 | Nat | Ive | 27 |
| 105 | Don | Sok | 35 |
Esempio 2: Filtrare per orario
Se vuoi selezionare tutti gli ordini fatti nell'ultima ora:
SELECT *
FROM orders
WHERE order_date >= NOW() - INTERVAL '1 hour';
Nota quanto è comodo usare INTERVAL (intervallo di tempo).
Esempio 3: Raggruppare per mese
Vuoi contare il numero di ordini per ogni mese dell'anno corrente:
SELECT DATE_PART('month', order_date) AS order_month, COUNT(*) AS order_count
FROM orders
WHERE DATE_PART('year', order_date) = DATE_PART('year', CURRENT_DATE)
GROUP BY DATE_PART('month', order_date)
ORDER BY order_month;
Il raggruppamento viene fatto per numero del mese, e il risultato è ordinato per lo stesso.
Esempio di risultato:
| order_month | order_count |
|---|---|
| 1 | 120 |
| 2 | 95 |
| 3 | 134 |
| 4 | 110 |
| 5 | 42 |
Esempio 4: Estrarre il giorno della settimana
Vuoi sapere in quale giorno della settimana ci sono più ordini:
SELECT DATE_PART('dow', order_date) AS day_of_week, COUNT(*) AS order_count
FROM orders
GROUP BY DATE_PART('dow', order_date)
ORDER BY order_count DESC;
Il comando DATE_PART('dow') restituisce il giorno della settimana per ogni ordine come numero, dove 0 è domenica, 1 è lunedì, e così via. DOW è l'abbreviazione di DayOfWeek - giorno della settimana.
Esempio di risultato:
| day_of_week | order_count |
|---|---|
| 5 | 210 |
| 4 | 190 |
| 3 | 175 |
| 2 | 160 |
| 1 | 140 |
| 6 | 120 |
| 0 | 95 |
Attenzione agli errori tipici
Lavorare con le date spesso fa venire il mal di testa per via degli errori. Ecco alcuni problemi comuni che potresti incontrare:
Formato di data e orario: quando usi NOW() o qualsiasi funzione che restituisce una data con orario, controlla sempre il formato. Ad esempio, se confronti order_date con CURRENT_DATE, assicurati che l'orario venga ignorato o sia specificato chiaramente.
Data come stringa: spesso nei database le date sono salvate come stringhe (tipo testo). Se provi a usare funzioni per lavorare con le date (tipo DATE_PART()), otterrai un errore. Assicurati che i dati siano di tipo DATE o TIMESTAMP.
Fusi orari diversi: se il tuo server lavora in un fuso orario e i dati arrivano da un altro, può crearsi confusione. Considera di usare il tipo di dato TIMESTAMPTZ per la zona oraria.
GO TO FULL VERSION