Travailler avec les dates est un passage obligé en SQL, surtout dans l’analyse de séries temporelles, la gestion de planning, ou le calcul de durées.
🗓️ Module 8 – Dates & calendriers#
🎯 Objectifs#
À la fin de ce module, tu sauras :
- Extraire des composants de date (
YEAR
,MONTH
,DAY
, etc.) - Faire des calculs sur les dates (
+
,INTERVAL
,DATEDIFF
) - Générer un calendrier (dates continues)
- Gérer les formats de date/heure
📦 1. Types de champs date#
Selon la base, on trouve :
Type SQL | Description |
---|---|
DATE | Date seule (2024-12-31 ) |
TIMESTAMP / DATETIME | Date + heure (2024-12-31 14:15:00 ) |
TIME | Heure seule (14:15:00 ) |
DuckDB : DATE
, TIME
, TIMESTAMP
, TIMESTAMPTZ
PostgreSQL : idem
SQLite : tout est string → nécessite parsing manuel
🔍 2. Extraire des parties de date#
Méthodes les plus universelles :#
SELECT
EXTRACT(YEAR FROM date_commande) AS annee,
EXTRACT(MONTH FROM date_commande) AS mois,
EXTRACT(DOW FROM date_commande) AS jour_semaine
FROM commandes;
Ou dans DuckDB / PostgreSQL (alternatives) :
SELECT
YEAR(date_commande),
MONTH(date_commande),
DAY(date_commande),
WEEK(date_commande)
FROM commandes;
🧮 3. Calculs sur les dates#
🔹 Ajouter ou soustraire du temps :#
SELECT date_commande + INTERVAL '7 days' AS date_plus_7
FROM commandes;
Peut aussi s’écrire
DATE_ADD()
/DATE_SUB()
sur certains moteurs (MySQL)
🔹 Durée entre deux dates :#
SELECT
DATEDIFF('day', date_inscription, CURRENT_DATE) AS jours_depuis_inscription
FROM clients;
DuckDB / PostgreSQL :
SELECT
age(CURRENT_DATE, date_inscription) AS anciennete
FROM clients;
🧰 4. Fonctions utiles#
Fonction | Description | Exemple |
---|---|---|
CURRENT_DATE , NOW() | Date / timestamp du moment | NOW() |
DATE_TRUNC('month', date) | Tronquer une date au mois | 2024-06-14 → 2024-06-01 |
TO_DATE(str, 'YYYY-MM-DD') | Convertir texte → date | '2024-01-01' |
FORMAT(date, '%Y-%m') | Transformer une date en string formatée | 2024-06 |
🧱 5. Générer un calendrier (calendar table)#
DuckDB / PostgreSQL : avec une SEQUENCE
#
SELECT
DATE '2023-01-01' + INTERVAL i DAY AS jour
FROM generate_series(0, 364) t(i);
➡️ Obtenir une table de 365 jours consécutifs à partir d’un point de départ.
🧯 6. Pièges classiques#
⚠️ Piège | ✅ Solution |
---|---|
Comparer une DATE à un STRING | Toujours CAST('2024-01-01' AS DATE) |
Manquer les jours sans données | Utiliser une table de dates pour jointure |
Formater à l’affichage avec TO_CHAR ou FORMAT | Évite de perdre la structure date |
🏋️♂️ 7. Exercices#
Exo 1 – Extraire le mois et l’année de chaque commande#
Exo 2 – Calculer l’âge (en jours) depuis l’inscription d’un client#
Exo 3 – Générer un calendrier du 1er janvier au 31 décembre 2024, avec une colonne jour_semaine
#
Exo 4 – Grouper les commandes par semaine#
🧪 8. Exemple en Python + DuckDB#
duckdb.sql("""
SELECT
client_id,
date_commande,
YEAR(date_commande) AS annee,
MONTH(date_commande) AS mois,
date_commande + INTERVAL 7 DAY AS livraison_estimee
FROM commandes;
""").df()
📚 9. Ressources utiles#
Et suite de l’article#
On les a abordés partiellement dans le module précédent, mais pas tous de manière explicite et structurée comme tu le souhaites. Voici donc un complément ciblé pour mieux cerner :
🔁 Les fonctions essentielles sur les dates & temps (avec syntaxes courantes)#
✅ Compatibilité :#
Fonction | DuckDB | PostgreSQL | MySQL | SQLite |
---|---|---|---|---|
DATEADD | ❌* | ❌ | ✅ | ❌ |
DATEDIFF | ✅ | ✅** | ✅ | partielle |
INTERVAL | ✅ | ✅ | ✅ | ❌ |
EXTRACT | ✅ | ✅ | ✅ | ❌ |
* DuckDB utilise plutôt
+ INTERVAL
, pasDATEADD()
** PostgreSQL ne possède pasDATEDIFF()
en natif, maisage()
ou soustraction directe
🧮 1. DATEADD()
(MySQL, SQL Server, etc.)#
Ajoute un intervalle à une date :
SELECT DATEADD(DAY, 7, '2024-01-01') -- → '2024-01-08'
👉 DuckDB & PostgreSQL utilisent :
SELECT DATE '2024-01-01' + INTERVAL 7 DAY
🧮 2. DATEDIFF()
– Durée entre deux dates#
-- En MySQL / SQL Server
SELECT DATEDIFF('2024-01-15', '2024-01-01') -- 14
-- En DuckDB
SELECT DATEDIFF('day', DATE '2024-01-15', DATE '2024-01-01') -- -14
➡️ PostgreSQL : SELECT AGE(date1, date2)
ou date1 - date2
🔍 3. EXTRACT()
– Extraire une composante#
SELECT
EXTRACT(YEAR FROM date_commande),
EXTRACT(MONTH FROM date_commande),
EXTRACT(DOW FROM date_commande)
FROM commandes;
DOW
= Day Of Week (0 = dimanche sur PostgreSQL)
⌚ 4. INTERVAL
– Créer un intervalle#
-- DuckDB / PostgreSQL
SELECT CURRENT_DATE + INTERVAL '1 month'
-- DuckDB supporte aussi :
SELECT CURRENT_DATE + INTERVAL 3 DAY
MySQL :
DATE_ADD(NOW(), INTERVAL 1 MONTH)
🔄 5. Troncature : DATE_TRUNC()
#
SELECT DATE_TRUNC('month', date_commande) AS debut_mois
FROM commandes;
Unité | Résultat typique |
---|---|
'day' | 2024-06-14 |
'month' | 2024-06-01 |
'week' | 2024-06-10 (début semaine) |
'year' | 2024-01-01 |
📅 6. Formatage & parsing#
🔹 Conversion texte → date#
SELECT TO_DATE('2024-01-01', 'YYYY-MM-DD') -- PostgreSQL
DuckDB : tu peux caster directement ou utiliser STRPTIME
:
SELECT STRPTIME('2024/01/01', '%Y/%m/%d')
🔹 Formatage date → texte#
SELECT STRFTIME(date, '%Y-%m') AS mois
✅ Récap rapide#
Objectif | DuckDB / PostgreSQL | MySQL / SQL Server |
---|---|---|
Ajouter une durée | + INTERVAL 1 MONTH | DATEADD(MONTH, 1, ...) |
Différence entre 2 dates | DATEDIFF('day', a, b) | DATEDIFF(a, b) |
Extraire une composante | EXTRACT(MONTH FROM date) | MONTH(date) |
Formater date → string | STRFTIME(date, '%Y-%m') | DATE_FORMAT(date, ...) |
Générer un début de mois | DATE_TRUNC('month', date) | DATE_FORMAT(..., '%Y-%m-01') |
Convertir string → date | STRPTIME(...) , CAST(...) | STR_TO_DATE(...) |