Regrouper le CA par mois
Chaque moteur a sa fonction pour tronquer une date : DATE_TRUNC en PostgreSQL, DATE_FORMAT en MySQL, DATEFROMPARTS ou FORMAT en SQL Server. Tronquer au premier jour du mois garde un résultat triable comme une vraie date.
-- PostgreSQL
SELECT DATE_TRUNC('month', cree_le) AS mois,
SUM(montant) AS ca
FROM commandes
GROUP BY 1
ORDER BY 1;
-- MySQL
SELECT DATE_FORMAT(cree_le, '%Y-%m-01') AS mois, SUM(montant)
FROM commandes GROUP BY mois ORDER BY mois;Filtrer une période sans casser l'index
Écrire WHERE YEAR(cree_le) = 2025 applique une fonction à chaque ligne : la base ne peut plus utiliser l'index et parcourt toute la table. Utilisez un intervalle semi-ouvert, compatible avec l'index et correct même avec des heures.
SELECT *
FROM commandes
WHERE cree_le >= '2025-01-01'
AND cree_le < '2026-01-01';Les 30 derniers jours
Utilisez la date courante de votre moteur : CURRENT_DATE - INTERVAL '30 days' en PostgreSQL, CURDATE() - INTERVAL 30 DAY en MySQL, DATEADD(day, -30, GETDATE()) en SQL Server. Décidez si « 30 jours » inclut aujourd'hui : finance et tableaux de bord divergent souvent, et l'écart se voit dans les totaux.
Comparer avec l'année précédente
Agrégez d'abord par mois, puis utilisez LAG avec un décalage de 12 pour récupérer le même mois de l'année précédente. Pas d'auto-jointure, et le taux de croissance en une passe. NULLIF évite la division par zéro pour les nouveaux produits.
WITH m AS (
SELECT DATE_TRUNC('month', cree_le) AS mois, SUM(montant) AS ca
FROM commandes GROUP BY 1
)
SELECT mois, ca,
LAG(ca, 12) OVER (ORDER BY mois) AS ca_n_1,
ROUND(100.0 * (ca - LAG(ca, 12) OVER (ORDER BY mois))
/ NULLIF(LAG(ca, 12) OVER (ORDER BY mois), 0), 1) AS croissance_pct
FROM m
ORDER BY mois;Les mois sans vente
GROUP BY ne renvoie que les mois qui ont des lignes : un mois à zéro disparaît du graphique. Générez un calendrier (generate_series en PostgreSQL, CTE récursive ailleurs) et faites un LEFT JOIN de vos agrégats avec COALESCE(ca, 0). Pensez aussi aux fuseaux : stockez en UTC et convertissez avec AT TIME ZONE avant de tronquer si le rapport est local.

