SQL est le 2e langage le plus utilisé par les développeurs en 2026 (58 % selon l’enquête Stack Overflow), juste derrière JavaScript. Voici les 40 requêtes SQL indispensables, classées par usage : SELECT, filtres, tris, GROUP BY, jointures, sous-requêtes, CTE et fonctions de fenêtrage. Toutes ont été testées sur le même jeu de données : copie-le et suis l’antisèche en pratique.
Ces requêtes SQL suivent la norme et fonctionnent avec MySQL 8, MariaDB, PostgreSQL et SQLite. Les rares différences entre ces systèmes sont signalées à la fin. (source : Stack Overflow Developer Survey 2026)

crée les trois tables ci-dessous dans ta base (MySQL, PostgreSQL ou SQLite), puis exécute les requêtes SQL dans l’ordre. Tu verras immédiatement leur résultat.
Le jeu de données d’exemple
Toutes les requêtes SQL de cette antisèche utilisent trois tables simples : des clients, des produits et des commandes qui les relient. Pour comprendre comment concevoir ce genre de schéma, lis notre guide Modéliser une base de données.

-- Jeu de données utilisé dans toute l'antisèche
CREATE TABLE clients (
id INTEGER PRIMARY KEY,
nom VARCHAR(100) NOT NULL,
email VARCHAR(150) UNIQUE,
ville VARCHAR(80),
cree_le DATE
);
CREATE TABLE produits (
id INTEGER PRIMARY KEY,
nom VARCHAR(100) NOT NULL,
categorie VARCHAR(50),
prix DECIMAL(8,2) NOT NULL
);
CREATE TABLE commandes (
id INTEGER PRIMARY KEY,
client_id INTEGER REFERENCES clients(id),
produit_id INTEGER REFERENCES produits(id),
quantite INTEGER NOT NULL DEFAULT 1,
date_commande DATE NOT NULL
);
INSERT INTO clients (id, nom, email, ville, cree_le) VALUES
(1, 'Alice', '[email protected]', 'Bruxelles', '2026-01-10'),
(2, 'Bruno', '[email protected]', 'Liège', '2026-02-03'),
(3, 'Chloé', '[email protected]', 'Namur', '2026-03-15'),
(4, 'David', NULL, 'Bruxelles', '2026-04-01');
INSERT INTO produits (id, nom, categorie, prix) VALUES
(1, 'Clavier', 'Accessoires', 49.90),
(2, 'Souris', 'Accessoires', 19.90),
(3, 'Écran 27"', 'Écrans', 229.00),
(4, 'Laptop', 'Ordinateurs', 899.00);
INSERT INTO commandes (client_id, produit_id, quantite, date_commande) VALUES
(1, 1, 1, '2026-05-02'), (1, 3, 2, '2026-05-10'), (2, 2, 3, '2026-05-11'),
(2, 4, 1, '2026-06-01'), (3, 2, 1, '2026-06-15'), (1, 4, 1, '2026-07-20');SQLRequêtes SQL pour lire des données : SELECT (1 à 4)
-- 1. Toutes les colonnes
SELECT * FROM clients;
-- 2. Certaines colonnes seulement
SELECT nom, email FROM clients;
-- 3. Valeurs uniques
SELECT DISTINCT ville FROM clients;
-- 4. Renommer une colonne (alias)
SELECT nom AS client, ville AS localite FROM clients;SQLRequêtes SQL pour filtrer : WHERE (5 à 10)
-- 5. Condition simple
SELECT nom, prix FROM produits WHERE prix > 50;
-- 6. Plusieurs conditions
SELECT * FROM clients WHERE ville = 'Bruxelles' AND email IS NOT NULL;
-- 7. Liste de valeurs
SELECT * FROM produits WHERE categorie IN ('Écrans', 'Ordinateurs');
-- 8. Intervalle (bornes incluses)
SELECT * FROM produits WHERE prix BETWEEN 20 AND 300;
-- 9. Recherche par motif : commence par « B »
SELECT * FROM clients WHERE nom LIKE 'B%';
-- 10. Valeurs manquantes (jamais "= NULL" !)
SELECT * FROM clients WHERE email IS NULL;SQLWHERE email = NULL ne renvoie jamais rien. En SQL, on teste l’absence de valeur avec IS NULL ou IS NOT NULL.
Requêtes SQL pour trier et limiter : ORDER BY, LIMIT (11 et 12)
-- 11. Les 3 produits les plus chers
SELECT nom, prix FROM produits ORDER BY prix DESC LIMIT 3;
-- 12. Pagination : 2 résultats en sautant les 2 premiers
SELECT nom, prix FROM produits ORDER BY prix LIMIT 2 OFFSET 2;SQLRequêtes SQL d’agrégation : COUNT, SUM, GROUP BY, HAVING (13 à 16)
-- 13. Compter des lignes
SELECT COUNT(*) AS nb_clients FROM clients;
-- 14. Somme, moyenne, minimum, maximum
SELECT SUM(quantite) AS total, AVG(quantite) AS moyenne,
MIN(date_commande) AS premiere, MAX(date_commande) AS derniere
FROM commandes;
-- 15. Regrouper : nombre de clients par ville
SELECT ville, COUNT(*) AS nb FROM clients GROUP BY ville;
-- 16. Filtrer des groupes : clients avec au moins 2 commandes
SELECT client_id, COUNT(*) AS nb
FROM commandes
GROUP BY client_id
HAVING COUNT(*) >= 2;SQLWHERE filtre les lignes avant le regroupement ; HAVING filtre les groupes après le GROUP BY.
Requêtes SQL avec jointures : combiner des tables (17 à 20)
-- 17. INNER JOIN : seulement les lignes qui correspondent
SELECT c.nom, p.nom AS produit, co.quantite
FROM commandes co
INNER JOIN clients c ON c.id = co.client_id
INNER JOIN produits p ON p.id = co.produit_id;
-- 18. LEFT JOIN : tous les clients, même sans commande
SELECT c.nom, co.id AS commande
FROM clients c
LEFT JOIN commandes co ON co.client_id = c.id;
-- 19. Les clients qui n'ont jamais commandé
SELECT c.nom
FROM clients c
LEFT JOIN commandes co ON co.client_id = c.id
WHERE co.id IS NULL;
-- 20. Chiffre d'affaires par client
SELECT c.nom, SUM(p.prix * co.quantite) AS chiffre
FROM commandes co
JOIN clients c ON c.id = co.client_id
JOIN produits p ON p.id = co.produit_id
GROUP BY c.nom
ORDER BY chiffre DESC;SQLLes jointures sont au cœur des requêtes SQL. Elles te posent encore question ? Notre article Jointures SQL expliquées : INNER, LEFT, RIGHT JOIN les détaille avec des schémas.

Sous-requêtes SQL, EXISTS et UNION (21 à 23)
-- 21. Sous-requête : produits plus chers que la moyenne
SELECT nom FROM produits
WHERE prix > (SELECT AVG(prix) FROM produits);
-- 22. EXISTS : clients ayant au moins une commande
SELECT nom FROM clients c
WHERE EXISTS (SELECT 1 FROM commandes co WHERE co.client_id = c.id);
-- 23. UNION : fusionner deux résultats sans doublons
SELECT ville FROM clients
UNION
SELECT 'Gand';SQLConditions et fonctions utiles (requêtes 24 à 26)
-- 24. CASE : catégoriser des valeurs
SELECT nom, prix,
CASE
WHEN prix < 50 THEN 'petit prix'
WHEN prix < 300 THEN 'moyen'
ELSE 'premium'
END AS gamme
FROM produits;
-- 25. COALESCE : remplacer les NULL
SELECT nom, COALESCE(email, 'non renseigné') AS email FROM clients;
-- 26. Fonctions de texte
-- (MySQL : LENGTH compte les octets, CHAR_LENGTH les caractères)
SELECT UPPER(nom) AS majuscules, LENGTH(nom) AS longueur FROM clients;SQLLes CTE avec WITH (requête 27)
Dans les requêtes SQL, une CTE (Common Table Expression) donne un nom à une sous-requête. Le code devient plus lisible, surtout quand la requête grandit. (source : MySQL : WITH (CTE))
-- 27. CTE : nommer une sous-requête pour la réutiliser
WITH ventes AS (
SELECT client_id, SUM(quantite) AS total
FROM commandes
GROUP BY client_id
)
SELECT c.nom, v.total
FROM ventes v
JOIN clients c ON c.id = v.client_id
WHERE v.total > 1;SQLRequêtes SQL avec fonctions de fenêtrage (28 à 32)
Dans les requêtes SQL modernes, une fonction de fenêtrage calcule une valeur sur un ensemble de lignes liées à la ligne courante, sans les regrouper : chaque ligne reste visible. On la reconnaît au mot-clé OVER. Elles sont disponibles dans MySQL 8, PostgreSQL et SQLite (depuis la version 3.25). (sources : MySQL : fonctions de fenêtrage, PostgreSQL : fonctions de fenêtrage, SQLite : window functions)
-- 28. ROW_NUMBER : numéroter les lignes
SELECT nom, prix, ROW_NUMBER() OVER (ORDER BY prix DESC) AS rang
FROM produits;
-- 29. RANK par groupe : classement dans chaque catégorie
SELECT categorie, nom, prix,
RANK() OVER (PARTITION BY categorie ORDER BY prix DESC) AS rang
FROM produits;
-- 30. Total cumulé
SELECT date_commande, quantite,
SUM(quantite) OVER (ORDER BY date_commande) AS cumul
FROM commandes;
-- 31. LAG : comparer avec la ligne précédente
SELECT date_commande, quantite,
LAG(quantite) OVER (ORDER BY date_commande) AS precedente
FROM commandes;
-- 32. Part de chaque produit dans le total
SELECT nom, prix,
ROUND(prix * 100.0 / SUM(prix) OVER (), 1) AS pourcentage
FROM produits;SQL
Requêtes SQL pour modifier les données : INSERT, UPDATE, DELETE (33 à 35)
-- 33. Ajouter une ligne
INSERT INTO clients (nom, email, ville, cree_le)
VALUES ('Emma', '[email protected]', 'Gand', '2026-11-09');
-- 34. Modifier des lignes (toujours avec un WHERE !)
UPDATE produits SET prix = prix * 1.05 WHERE categorie = 'Accessoires';
-- 35. Supprimer des lignes (toujours avec un WHERE !)
DELETE FROM commandes WHERE date_commande < '2026-05-05';SQLexécute d’abord un SELECT avec le même WHERE pour vérifier les lignes concernées. Sans WHERE, toute la table est modifiée.
Gérer la structure : ALTER, INDEX, DROP (requêtes 36 à 38)
-- 36. Ajouter une colonne
ALTER TABLE clients ADD COLUMN telephone VARCHAR(20);
-- 37. Créer un index pour accélérer les recherches
CREATE INDEX idx_commandes_client ON commandes (client_id);
-- 38. Supprimer une table (irréversible)
DROP TABLE IF EXISTS archives;SQLUn index bien choisi peut rendre des requêtes SQL des centaines de fois plus rapide. Voir notre guide Optimiser une requête MySQL lente.
Transactions et EXPLAIN (requêtes 39 et 40)
-- 39. Transaction : tout ou rien
BEGIN;
UPDATE produits SET prix = prix - 10 WHERE id = 4;
INSERT INTO commandes (client_id, produit_id, quantite, date_commande)
VALUES (3, 4, 1, '2026-11-09');
COMMIT; -- ou ROLLBACK; pour tout annuler
-- 40. Comprendre comment la requête est exécutée
EXPLAIN SELECT * FROM commandes WHERE client_id = 1;SQLLes différences entre MySQL, PostgreSQL et SQLite
| Besoin | MySQL / MariaDB | PostgreSQL | SQLite |
|---|---|---|---|
| Clé auto-incrémentée | AUTO_INCREMENT | GENERATED ALWAYS AS IDENTITY | INTEGER PRIMARY KEY |
| Concaténer du texte | CONCAT(a, b) | a || b ou CONCAT | a || b |
| Date du jour | CURDATE() | CURRENT_DATE | DATE('now') |
| Recherche insensible à la casse | LIKE (selon la collation) | ILIKE | LIKE (ASCII) |
| Démarrer une transaction | START TRANSACTION ou BEGIN | BEGIN | BEGIN |
Ces requêtes SQL marchent sur les deux grands SGBD. Tu hésites entre les deux ? Lis notre comparatif PostgreSQL ou MySQL.
L’ordre d’exécution des requêtes SQL
On écrit les requêtes SQL dans un ordre, mais la base l’exécute dans un autre. Le comprendre explique pourquoi un alias défini dans le SELECT n’est pas utilisable dans le WHERE.

FROMetJOINWHEREGROUP BYHAVINGSELECT(et les fonctions de fenêtrage)DISTINCTORDER BYLIMIT/OFFSET
FAQ
Quelles sont les requêtes SQL les plus utilisées ?
SELECT avec WHERE, ORDER BY, les jointures (INNER et LEFT JOIN), GROUP BY avec COUNT ou SUM, puis INSERT, UPDATE et DELETE.
Quelle différence entre INNER JOIN et LEFT JOIN ?
INNER JOIN ne garde que les lignes présentes dans les deux tables. LEFT JOIN garde toutes les lignes de la table de gauche, avec NULL quand il n’y a pas de correspondance.
À quoi servent les fonctions de fenêtrage ?
À calculer des classements, des totaux cumulés ou des comparaisons entre lignes sans perdre le détail de chaque ligne, contrairement à GROUP BY.
Ces requêtes SQL fonctionnent-elles avec MySQL ?
Oui, avec MySQL 8 et plus récent. Les fonctions de fenêtrage et les CTE n’existent pas dans MySQL 5.7.
Requêtes SQL : le résumé à retenir
- Lire : SELECT, WHERE, ORDER BY, LIMIT.
- Résumer : COUNT, SUM, GROUP BY, HAVING.
- Combiner : INNER JOIN, LEFT JOIN, sous-requêtes, UNION.
- Analyser : CTE et fonctions de fenêtrage (OVER).
- Modifier : INSERT, UPDATE, DELETE, toujours avec un WHERE.
Conclusion
Avec ces 40 requêtes SQL, tu couvres l’essentiel du SQL utilisé au quotidien, du simple SELECT aux analyses avec les fonctions de fenêtrage. Garde cette antisèche des requêtes SQL dans tes favoris, et entraîne-toi sur le jeu de données jusqu’à écrire chaque requête sans la regarder.
Sources
- Stack Overflow : 2026 Developer Survey results
- MySQL 8.4 Reference Manual : Window Functions
- MySQL 8.4 Reference Manual : WITH (Common Table Expressions)
- PostgreSQL : Window Functions
- SQLite : Window Functions

