Aller au contenu principal
SQLBase de donnéesFormationData

SELECT, INSERT, UPDATE : tes premières requêtes

30 min de lecture Apprendre SQL — Chapitre 2

Maîtrise ORDER BY, LIMIT, les fonctions d'agrégation (COUNT, SUM, AVG), GROUP BY et HAVING. Avec des exemples pratiques DevOps.

Dans le chapitre précédent, on a vu Pourquoi SQL ? Les bases de données expliquées. Tu sais maintenant interroger des données avec SELECT et WHERE. On passe au niveau suivant.

🎯 Objectif : Maîtriser le tri avec ORDER BY, la pagination avec LIMIT, les fonctions d’agrégation (COUNT, SUM, AVG) et le regroupement avec GROUP BY / HAVING.

ORDER BY et LIMIT : trier et paginer

Sans ORDER BY, SQL ne garantit aucun ordre de résultat. Deux exécutions de la même requête peuvent donner des ordres différents. Si tu veux un résultat prévisible, trie explicitement.

-- Tri alphabétique (ASC par défaut)
SELECT * FROM servers ORDER BY hostname;

-- Tri décroissant par RAM
SELECT * FROM servers ORDER BY ram_gb DESC;

-- Tri multi-colonnes : d'abord par env, puis par CPU décroissant
SELECT * FROM servers
ORDER BY environment ASC, cpu_cores DESC;

-- Les 3 serveurs avec le plus de RAM
SELECT hostname, ram_gb FROM servers
ORDER BY ram_gb DESC
LIMIT 3;

-- Pagination : résultats 21 à 30
SELECT * FROM servers
ORDER BY server_id
LIMIT 10 OFFSET 20;

💡 LIMIT sans ORDER BY est un piège classique. Tu obtiens des résultats “aléatoires” — pas vraiment utile. Combine toujours les deux.

⚠️ En SQL Server, la syntaxe est SELECT TOP 5 * FROM servers au lieu de LIMIT. Le concept reste identique.

Fonctions d’agrégation

Les fonctions d’agrégation transforment un ensemble de lignes en une seule valeur. Ce sont les outils d’analyse de SQL.

Les 5 fonctions essentielles

-- Combien de serveurs au total ?
SELECT COUNT(*) AS total_servers FROM servers;

-- Compter les valeurs non-NULL uniquement
SELECT COUNT(ip_address) AS servers_with_ip FROM servers;

-- Somme des CPUs de tout le parc
SELECT SUM(cpu_cores) AS total_cpus FROM servers;

-- RAM moyenne (arrondie)
SELECT ROUND(AVG(ram_gb), 1) AS avg_ram FROM servers;

-- Min et Max en une requête
SELECT MIN(cpu_cores) AS min_cpus,
       MAX(cpu_cores) AS max_cpus
FROM servers;

-- Combiner agrégation et WHERE
SELECT SUM(ram_gb) AS total_prod_ram
FROM servers
WHERE environment = 'production';

🔥 COUNT(*) compte toutes les lignes, COUNT(colonne) ignore les NULL. C’est une nuance importante quand tu as des données incomplètes.

GROUP BY : regrouper les données

GROUP BY est la clause qui rend SQL vraiment puissant pour l’analyse. Elle regroupe les lignes partageant une même valeur, puis applique une agrégation sur chaque groupe.

-- Nombre de serveurs par environnement
SELECT environment,
       COUNT(*) AS server_count
FROM servers
GROUP BY environment;
environmentserver_count
production3
development1
staging1

Regroupement avec plusieurs agrégations

-- Stats complètes par environnement
SELECT environment,
       COUNT(*) AS nb_servers,
       SUM(ram_gb) AS total_ram,
       ROUND(AVG(cpu_cores), 1) AS avg_cpus
FROM servers
GROUP BY environment
ORDER BY total_ram DESC;

Regroupement multi-colonnes

-- Serveurs par environnement ET par statut
SELECT environment, status,
       COUNT(*) AS server_count
FROM servers
GROUP BY environment, status
ORDER BY environment, status;

💡 Règle d’or : toute colonne dans le SELECT qui n’est pas dans une fonction d’agrégation doit apparaître dans le GROUP BY. Sinon, PostgreSQL te renvoie une erreur.

HAVING : filtrer les groupes

WHERE filtre les lignes avant le regroupement. HAVING filtre les groupes après l’agrégation. C’est la distinction la plus importante de ce chapitre.

-- Environnements avec plus de 2 serveurs
SELECT environment, COUNT(*) AS server_count
FROM servers
GROUP BY environment
HAVING COUNT(*) > 2;

-- Environnements avec plus de 20 Go de RAM totale
SELECT environment, SUM(ram_gb) AS total_ram
FROM servers
GROUP BY environment
HAVING SUM(ram_gb) > 20;

WHERE + HAVING combinés

-- Parmi les serveurs actifs, quels envs ont 2+ serveurs ?
SELECT environment,
       COUNT(*) AS running_count,
       ROUND(AVG(cpu_cores), 1) AS avg_cpus
FROM servers
WHERE status = 'running'          -- filtre les lignes
GROUP BY environment
HAVING COUNT(*) >= 2              -- filtre les groupes
ORDER BY running_count DESC;

⚠️ L’ordre d’exécution SQL n’est pas l’ordre d’écriture. SQL exécute : FROMWHEREGROUP BYHAVINGSELECTORDER BYLIMIT. C’est pour ça qu’un alias défini dans SELECT n’est pas utilisable dans WHERE — le WHERE s’exécute avant.

Cas entreprise : tableau de bord des déploiements

Un SRE gère des centaines de déploiements par semaine. Sans SQL, il ouvre des dashboards. Avec SQL, il crée ses propres analyses en temps réel.

-- Table deployments : deploy_id, service, environment,
-- version, deployed_by, deploy_time, status, duration_sec

-- Les 10 derniers déploiements
SELECT service, environment, version, deploy_time, status
FROM deployments
ORDER BY deploy_time DESC
LIMIT 10;

-- Déploiements par service ce mois, avec taux d'échec
SELECT service,
       COUNT(*) AS total,
       COUNT(CASE WHEN status = 'failed' THEN 1 END) AS failures,
       ROUND(
         100.0 * COUNT(CASE WHEN status = 'failed' THEN 1 END) / COUNT(*), 1
       ) AS failure_rate
FROM deployments
WHERE deploy_time >= '2026-03-01'
GROUP BY service
ORDER BY failure_rate DESC;

-- Durée moyenne par environnement (succès uniquement)
SELECT environment,
       ROUND(AVG(duration_sec), 0) AS avg_duration,
       MIN(duration_sec) AS fastest,
       MAX(duration_sec) AS slowest
FROM deployments
WHERE status = 'success'
GROUP BY environment;

-- Services "bruyants" : plus de 5 échecs depuis janvier
SELECT service, COUNT(*) AS failures
FROM deployments
WHERE status = 'failed' AND deploy_time >= '2026-01-01'
GROUP BY service
HAVING COUNT(*) > 5
ORDER BY failures DESC;

🎯 La requête avec CASE WHEN dans un COUNT est un pattern essentiel. Elle permet de calculer des taux (succès, échec, conversion) en une seule passe. Tu la retrouveras partout en analytics.

Pièges et bonnes pratiques

⚠️ Les erreurs classiques à éviter :

  • LIMIT sans ORDER BY — Résultats imprévisibles. Toujours trier avant de limiter.
  • GROUP BY sans toutes les colonnes — Chaque colonne du SELECT non agrégée doit être dans le GROUP BY. PostgreSQL est strict là-dessus (MySQL moins, ce qui cause des bugs silencieux).
  • WHERE avec une agrégationWHERE COUNT(*) > 5 ne compile pas. C’est HAVING COUNT(*) > 5.
  • OFFSET élevé sur de grosses tablesOFFSET 100000 force PostgreSQL à scanner 100 000 lignes pour les ignorer. Pour la pagination performante, utilise un curseur basé sur l’ID : WHERE server_id > 100000 LIMIT 10.
  • Oublier ROUND sur les moyennesAVG retourne souvent 15 décimales. Un ROUND(AVG(col), 1) rend le résultat lisible.

💡 Astuce pro : utilise \x dans psql pour activer l’affichage étendu quand tu as beaucoup de colonnes. Chaque colonne s’affiche sur sa propre ligne — bien plus lisible.

Résumé

🔥 Ce qu’on a couvert : ORDER BY pour trier les résultats (toujours explicite !), LIMIT / OFFSET pour la pagination, les fonctions d’agrégation (COUNT, SUM, AVG, MIN, MAX) pour analyser les données, GROUP BY pour regrouper, et HAVING pour filtrer les groupes après agrégation.

L’ordre d’exécution SQL (FROMWHEREGROUP BYHAVINGSELECTORDER BYLIMIT) explique pourquoi certaines syntaxes marchent et d’autres non. Retiens-le — ça t’évitera des heures de debugging.

💡 À retenir : WHERE filtre les lignes, HAVING filtre les groupes. Si tu confonds les deux, PostgreSQL te le dira clairement. C’est la distinction fondamentale de ce chapitre.

Articles liés