Quels analytics patterns maîtriser en data science ?

Les quatre patterns SQL essentiels sont joins+filters, window functions, aggregation/grouping (roll‑up) et pivoting, capables de résoudre la majorité des analyses décisionnelles (voir PostgreSQL documentation). Suivez les séquences pratiques, exemples PostgreSQL et cas métier concrets pour les appliquer immédiatement.

Comment isoler le bon sous‑ensemble avec JOIN et WHERE

Isoler le bon sous‑ensemble commence par choisir la table principale, puis joindre les tables de contexte et enfin filtrer avant d’agréger. J’insiste sur ce point parce que filtrer après agrégation ou joindre de travers conduit à des biais, des doublons et des coûts inutiles.

Séquence recommandée et explication :

La séquence suivante minimise les erreurs et optimise les performances :

Comme on dit à Brive, un bon plan de marquage vaut mieux qu’un bon reporting ! Si besoin, consultez moi - faites appel à un super consultant en tracking client et server side.

  • Choisir la table primaire — Celle qui représente l’entité analysée (ex : commandes, employés, vols).
  • Joindre les contextes nécessaires — Utiliser INNER JOIN si l’existence est requise, LEFT JOIN si l’absence est informative.
  • Appliquer des filtres sur colonnes non agrégées (WHERE) — Filtrer avant agrégation pour réduire les données traitées.
  • Agréger si besoin et filtrer résultats agrégés (HAVING) — Utiliser HAVING uniquement pour conditions sur agrégats.

Exemples métier concrets :

  • RH — Identifier les heures sup en joignant feuille de temps + contrats et filtrant par période avant d’agréger.
  • Retail — Extraire les produits d’une commande en joignant commandes → lignes de commande → produits puis filtrant par statut.
  • Streaming — Suggérer des films adaptés à la durée d’un vol en comparant duration film ≤ durée vol et en triant par popularité.

Exemple PostgreSQL : recommander films compatibles avec un vol

CREATE TABLE movies (id SERIAL PRIMARY KEY, title TEXT, duration INT, popularity NUMERIC);
CREATE TABLE flights (id SERIAL PRIMARY KEY, user_id INT, duration INT);

-- Retourne jusqu'à 10 films dont la durée est <= durée du vol, triés par popularité
SELECT m.id, m.title, m.duration, m.popularity
FROM flights f
JOIN movies m ON m.duration <= f.duration
WHERE f.id = 123 -- vol ciblé
ORDER BY m.popularity DESC
LIMIT 10;

Alternatives, astuces et pièges :

EXISTS évite la multiplication de lignes quand seule l'existence compte. J'encourage d'appliquer les filtres avant les JOIN pour réduire I/O. Indexez les colonnes de jointure et de filtre. Méfiez-vous des JOIN multiples qui multiplient les lignes; utilisez DISTINCT ou agrégations correctement pour corriger.

Pattern Séquence SQL Snippet Cas métier
Isoler sous‑ensemble Choix → JOIN → WHERE → AGG → HAVING JOIN + WHERE avant GROUP BY Streaming, Retail, RH

Quand utiliser les fonctions fenêtre pour classer

Quand il faut classer et extraire un top N par groupe sans perdre les colonnes de détail, utilisez les fonctions fenêtre.

J'utilise systématiquement ROW_NUMBER, RANK et DENSE_RANK pour ces besoins, car elles permettent de partitionner, trier et attribuer un rang sans agrégation destructrice.

  • Séquence essentielle : Partitionner (PARTITION BY), Ordonner (ORDER BY), Appliquer la fonction de fenêtre, Encapsuler le tout dans une CTE pour filtrer le top N.
  • Cas métier typiques : Top vendeurs par région, Meilleurs étudiants par classe, Top articles par canal.

Différences pratiques :

  • ROW_NUMBER donne un rang unique par ligne (ordinal). Utile quand on veut exactement N lignes, même en présence d'ex æquo.
  • RANK donne le même rang aux ex æquo mais crée des trous (gaps) dans les rangs suivants. Utile pour dire « ex æquo au rang 1, suivant = rang 3 ».
  • DENSE_RANK donne le même rang aux ex æquo sans trous. Utile pour classement où les rangs doivent rester consécutifs.

Exemple PostgreSQL complet (table posts(id, channel_id, likes, created_at)) :

WITH ranked AS (
  SELECT
    id,
    channel_id,
    likes,
    created_at,
    ROW_NUMBER() OVER (PARTITION BY channel_id ORDER BY likes DESC, created_at DESC) AS rn
  FROM posts
)
SELECT id, channel_id, likes, created_at
FROM ranked
WHERE rn <= 3
ORDER BY channel_id, rn;

Exemple montrant RANK vs DENSE_RANK pour gérer les ex æquo :

SELECT id, channel_id, likes,
  RANK() OVER (PARTITION BY channel_id ORDER BY likes DESC)    AS r_rank,
  DENSE_RANK() OVER (PARTITION BY channel_id ORDER BY likes DESC) AS d_rank
FROM posts
ORDER BY channel_id, likes DESC;

Performance et alternatives :

  • Penser à un index couvrant (channel_id, likes DESC, created_at) pour accélérer ORDER BY dans la fenêtre.
  • Évaluer la taille des partitions : les fonctions fenêtre traitent généralement toutes les lignes de la partition avant filtrage, donc coût mémoire/CPU.
  • Alternative pour top N global : FETCH FIRST ... WITH TIES (Postgres 13+). Pour top-1 par groupe, DISTINCT ON(channel_id) ou LATERAL JOIN + LIMIT peuvent être plus rapides selon le cas.
Fonction Comportement Cas d'utilisation Extrait SQL
ROW_NUMBER Rang unique, pas d'égalité Top N strict ROW_NUMBER() OVER (PARTITION BY channel_id ORDER BY likes DESC)
RANK Égalités = même rang, crée des gaps Afficher ex æquo et conserver positions originales RANK() OVER (PARTITION BY channel_id ORDER BY likes DESC)
DENSE_RANK Égalités = même rang, pas de gaps Classement consécutif malgré ex æquo DENSE_RANK() OVER (PARTITION BY channel_id ORDER BY likes DESC)

Comment agréger par dimensions avec le roll up

Le roll-up consiste à grouper par une ou plusieurs dimensions puis appliquer des agrégats (COUNT, SUM) pour résumer les données et détecter tendances ou outliers.

Choix de la dimension et séquence opérationnelle importante pour obtenir un résumé pertinent :

  • Choisir la dimension analytique : Sélectionner la granularité utile (jour, semaine, client, produit).
  • GROUP BY : Grouper par la ou les dimensions choisies.
  • Appliquer fonctions d'agrégation : Utiliser COUNT, SUM, AVG, MAX selon le besoin.
  • HAVING pour conditions sur agrégats : Filtrer les groupes (par exemple COUNT > 0, SUM > seuil).

Cas métier courants : e‑commerce (commandes et CA par client/jour), SaaS (connexions par semaine), finance (transactions par trimestre).

Exemple PostgreSQL concret : identifier les utilisateurs ayant lancé une session et passé une commande le même jour, avec COUNT(orders) et SUM(amount).

WITH session_days AS (
  SELECT DISTINCT user_id, started_at::date AS day
  FROM sessions
)
SELECT sd.user_id,
       sd.day,
       COUNT(o.id) AS orders_count,
       SUM(o.amount) AS total_amount
FROM session_days sd
JOIN orders o
  ON o.user_id = sd.user_id
  AND o.ordered_at::date = sd.day
GROUP BY sd.user_id, sd.day
HAVING COUNT(o.id) > 0
ORDER BY sd.user_id, sd.day;

Variante avec ROLLUP/GROUPING SETS : ROLLUP(user_id, day) produit des sous-totaux hiérarchiques (par user, puis global), tandis que GROUPING SETS permet de définir explicitement les combinaisons d'agrégats.

SELECT user_id::text,
       day::text,
       COUNT(id) AS orders_count,
       SUM(amount) AS total_amount
FROM orders
GROUP BY ROLLUP(user_id, day);

Implications performance : Cardinalité élevée alourdit le GROUP BY, privilégier index sur (user_id, ordered_at) ou index fonctionnel (ordered_at::date), utiliser agrégations partielles (map-reduce) ou materialized views pour pré-agréger si les requêtes sont fréquentes et le délai d'actualisation acceptable.

Tableau synthèse (étapes, SQL snippet, cas métier) :

Étape Action Exemple / Cas
1 Choisir dimension Jour/client — e‑commerce
2 GROUP BY + agrégats COUNT(id), SUM(amount)
3 HAVING pour filtrer HAVING SUM(amount) > 100
4 Optimiser Index, pré‑agrégation, materialized view

Comment transformer des lignes en colonnes avec pivot

Je détaille comment transformer des lignes en colonnes (pivot) en PostgreSQL, quand utiliser les agrégats conditionnels et quand recourir à tablefunc.crosstab.

  • Agrégats conditionnels : Utilisez SUM(CASE WHEN ...) ou SUM(...) FILTER(WHERE ...) pour produire des colonnes par catégorie sans extension.
  • Extension tablefunc.crosstab : Utilisez crosstab pour des tableaux croisés plus performants quand les colonnes sont connues à l'avance.
  • Cas métier concret : Tableau croisé des paiements par mois et méthode (pivot mois x méthode).
  • Cas métier concret : Comparatif de chiffre d'affaires (CA) par canal marketing.
  • Cas métier concret : Rapport de conversion par étape (funnel) pivoté par étape ou par segment.

Exemple A — Agrégats conditionnels (valeur maximale par méthode sur une période) :

SELECT
  date_trunc('month', paid_at) AS month,
  MAX(amount) FILTER (WHERE payment_method = 'card') AS card_max,
  MAX(amount) FILTER (WHERE payment_method = 'cash') AS cash_max,
  MAX(amount) FILTER (WHERE payment_method = 'bank') AS bank_max
FROM payments
WHERE paid_at BETWEEN '2025-01-01' AND '2025-03-31'
GROUP BY 1
ORDER BY 1;

Exemple B — crosstab (nécessite l'extension tablefunc, colonnes fixes) :

CREATE EXTENSION IF NOT EXISTS tablefunc;

SELECT *
FROM crosstab(
  'SELECT to_char(paid_at, ''YYYY-MM'') AS mon, payment_method, SUM(amount)
   FROM payments
   GROUP BY 1,2
   ORDER BY 1,2'
) AS ct(mon text, card numeric, cash numeric, bank numeric);

Avantages/Inconvénients :

  • Agrégats conditionnels : Lisibilité élevée, portable, supporte colonnes dynamiques via SQL dynamique, mais les requêtes peuvent devenir verbeuses pour beaucoup de colonnes.
  • Crosstab : Très efficace pour des pivots larges et lecture optimisée, mais nécessite de connaître les colonnes en avance et attention à la gestion des NULLs et des performances si données volumineuses.
Méthode Exemple SQL Contraintes Cas d'usage
Agrégats conditionnels MAX(...) FILTER (WHERE ...) Lisible, portable, verbeux si N colonnes Rapports ad hoc, dashboards simples
tablefunc.crosstab crosstab('SELECT ...') Colonnes fixes, extension requise Pivots larges, exports optimisés

Format final HTML requis : Utiliser les balises strong, p, ul, li, table, tbody, tr, td et inclure les requêtes SQL PostgreSQL lisibles dans des balises p ou table (ou dans <pre class="wp-block-code"><code> pour le code).

Prêt à appliquer ces patterns à vos données ?

Ces quatre patterns — joins+filters, window functions, aggregation/grouping (roll‑up) et pivoting — couvrent la plupart des besoins analytiques en SQL. Maîtrisez la séquence de chaque pattern, testez les exemples PostgreSQL fournis et adaptez‑les à vos schémas. Vous gagnerez en rapidité d'analyse et en robustesse des rapports, et réduirez temps d'investigation et erreurs. Bénéfice clair : produire des insights actionnables plus vite et à moindre coût.

FAQ

Quels patterns couvrent la majorité des requêtes analytiques ?
Les patterns essentiels sont : joins+filters (sélection du sous‑ensemble), window functions (classements et top N), aggregation/grouping (roll‑up) et pivoting (lignes→colonnes). Ils permettent de résoudre la plupart des besoins analytiques en SQL.
Quand choisir ROW_NUMBER plutôt que RANK ou DENSE_RANK ?
ROW_NUMBER est adapté quand vous voulez un rang unique (top N strict). RANK laisse des trous en cas d'ex æquo; DENSE_RANK conserve des rangs consécutifs pour les ex æquo. Choisissez selon le comportement souhaité pour les égalités.
Pivot dynamique ou agrégats conditionnels : que préférer ?
Les agrégats conditionnels (FILTER/CASE) sont simples et sûrs quand les colonnes cibles sont connues. Crosstab (tablefunc) offre un pivot dynamique mais exige l'extension tablefunc et une définition précise des colonnes de sortie, et peut être moins portable.
Comment optimiser les requêtes utilisant joins et agrégations ?
Appliquer les filtres tôt, limiter les colonnes sélectionnées, indexer les colonnes de jointure et de filtrage, tester plans d'exécution (EXPLAIN). Pour volumes élevés, envisager pré‑agrégation ou tables intermédiaires.
Où pratiquer ces patterns avec des exemples SQL ?
Pratiquez sur jeux de données publics ou plateformes d'exercices SQL qui proposent problèmes d'entretien et datasets. Implémentez les exemples fournis ici en PostgreSQL pour comprendre comportement et performances.

 

 

A propos de l'auteur

Franck Scandolera — expert & formateur en Tracking avancé server‑side, Analytics Engineering, Automatisation No/Low Code (n8n) et intégration d'IA en entreprise. Responsable de l'agence webAnalyste et de l'organisme de formation Formations Analytics. Références clients : Logis Hôtel, Yelloh Village, BazarChic, Fédération Française de Football, Texdecor. Dispo pour aider les entreprises => contactez moi.

Résumer ce contenu avec :
Retour en haut