Le problème : trouver une aiguille dans 10 000 produits
Votre boutique a maintenant 10 000 produits en base. Votre patron vous demande : « Donne-moi les 5 produits les plus chers du catalogue, juste le nom et le prix. »
Impossible de scroller à la main. Vous avez besoin d'un outil pour extraire précisément ce que vous voulez : certaines colonnes, certaines lignes, dans un certain ordre, en quantité limitée. C'est exactement le rôle de SELECT.
Pour toute cette leçon, on travaille sur une table produits :
id | nom | categorie | prix | stock
----+------------------+--------------+---------+------
1 | Clavier méca | informatique | 89.90 | 42
2 | Souris sans fil | informatique | 29.90 | 0
3 | Café en grains | epicerie | 12.50 | 120
4 | Mug isotherme | maison | 19.90 | 8
SELECT ... FROM : le duo de base
Toute lecture commence par deux mots-clés : SELECT (quelles colonnes ?) et FROM (dans quelle table ?).
SELECT nom, prix
FROM produits;
Cette requête renvoie uniquement les colonnes nom et prix de toutes les lignes. Le point-virgule final marque la fin de l'instruction.
Vous pouvez aussi tout demander avec l'étoile * :
SELECT *
FROM produits;
Évitez SELECT * en production. Il récupère toutes les colonnes, même celles dont vous n'avez pas besoin : c'est plus lent, ça consomme de la mémoire inutilement, et votre code casse silencieusement si l'ordre des colonnes change. Nommez toujours les colonnes voulues.
WHERE : ne garder que certaines lignes
Sans filtre, SELECT renvoie toutes les lignes. La clause WHERE ne garde que celles qui respectent une condition :
SELECT nom, prix
FROM produits
WHERE categorie = 'informatique';
Ici, seuls les produits de la catégorie informatique sortent. On peut comparer des nombres :
SELECT nom, prix
FROM produits
WHERE prix > 20;
Le texte se compare entre apostrophes simples ('informatique'), les nombres sans apostrophes (20). La leçon suivante explore WHERE en profondeur (AND, OR, LIKE, IN...).
DISTINCT : sans les doublons
Vous avez une table clients avec des centaines de lignes. Votre patron demande : « Donne-moi la liste des villes où on a des clients. » Vous écrivez :
SELECT ville FROM clients;
Résultat : Dijon, Lyon, Dijon, Dijon, Paris, Lyon... La même ville revient autant de fois qu'il y a de clients dedans. Ce n'est pas ce qu'on voulait. Le mot-clé DISTINCT élimine ces doublons :
SELECT DISTINCT ville FROM clients;
Maintenant la base renvoie chaque ville une seule fois : Dijon, Lyon, Paris. Trois lignes, pas cinquante.
DISTINCT sur plusieurs colonnes : c'est le couple qui est unique. SELECT DISTINCT ville, categorie FROM commandes ne cherche pas les villes uniques ET les catégories uniques séparément. Il cherche les couples (ville, catégorie) uniques. Si Dijon + informatique apparaît trois fois et Dijon + maison deux fois, vous obtenez deux lignes : une pour chaque couple distinct. Cela surprend souvent au premier abord.
ORDER BY et LIMIT : trier et limiter
ORDER BY trie le résultat. ASC = croissant (par défaut), DESC = décroissant.
On veut récupérer les 3 produits les plus chers de la table produits. Un collègue écrit : SELECT * FROM produits LIMIT 3. Avant de dérouler : cette requête renvoie-t-elle bien les 3 produits les plus chers ? Pourquoi ? Que faut-il ajouter ?
Voir la réponse
Non. LIMIT 3 se contente de renvoyer 3 lignes, mais sans ORDER BY l'ordre des lignes n'est pas garanti : la base les renvoie dans un ordre arbitraire (souvent l'ordre d'insertion, mais rien ne l'impose). On obtient donc 3 produits quelconques, pas les plus chers. Pour le « top 3 », il faut d'abord trier, puis limiter : SELECT * FROM produits ORDER BY prix DESC LIMIT 3. ORDER BY prix DESC classe du plus cher au moins cher, et LIMIT 3 ne garde que les 3 premiers de ce classement. L'ordre logique : on trie, puis on coupe.
SELECT nom, prix
FROM produits
ORDER BY prix DESC;
LIMIT coupe le résultat à un nombre de lignes. La demande du patron (les 5 produits les plus chers) devient :
SELECT nom, prix
FROM produits
ORDER BY prix DESC
LIMIT 5;
L'ordre des clauses est toujours le même : SELECT → FROM → WHERE → ORDER BY → LIMIT. Si vous l'inversez, la requête échoue.
Pour paginer (page 2, 10 par page), ajoutez OFFSET : LIMIT 10 OFFSET 10 saute les 10 premières lignes et renvoie les 10 suivantes.
Sans ORDER BY, aucun ordre n'est garanti. Le SGBD est libre de renvoyer les lignes dans l'ordre qui l'arrange (insertion, stockage interne, plan d'exécution). Même si le résultat paraît trié, c'est un hasard : ne comptez jamais dessus. Dès que l'ordre compte, écrivez-le explicitement avec ORDER BY.
The problem: finding a needle in 10,000 products
Your shop now has 10,000 products in the database. Your boss asks: "Give me the 5 most expensive products in the catalog, just the name and price."
You cannot scroll by hand. You need a tool to extract precisely what you want: some columns, some rows, in a certain order, in a limited quantity. This is exactly what SELECT does.
For this whole lesson, we work on a produits table:
id | nom | categorie | prix | stock
----+------------------+--------------+---------+------
1 | Clavier meca | informatique | 89.90 | 42
2 | Souris sans fil | informatique | 29.90 | 0
3 | Cafe en grains | epicerie | 12.50 | 120
4 | Mug isotherme | maison | 19.90 | 8
SELECT ... FROM: the basic duo
Every read starts with two keywords: SELECT (which columns?) and FROM (from which table?).
SELECT nom, prix
FROM produits;
This query returns only the nom and prix columns of all rows. The trailing semicolon marks the end of the statement.
You can also request everything with the star *:
SELECT *
FROM produits;
Avoid SELECT * in production. It fetches every column, even those you do not need: it is slower, wastes memory, and your code breaks silently if the column order changes. Always name the columns you want.
WHERE: keep only some rows
Without a filter, SELECT returns all rows. The WHERE clause keeps only those matching a condition:
SELECT nom, prix
FROM produits
WHERE categorie = 'informatique';
Here, only products in the informatique category come out. You can compare numbers:
SELECT nom, prix
FROM produits
WHERE prix > 20;
Text is compared between single quotes ('informatique'), numbers without quotes (20). The next lesson explores WHERE in depth (AND, OR, LIKE, IN...).
DISTINCT: without duplicates
You have a clients table with hundreds of rows. Your boss asks: "Give me the list of cities where we have customers." You write:
SELECT ville FROM clients;
Result: Dijon, Lyon, Dijon, Dijon, Paris, Lyon... The same city comes back as many times as there are customers in it. Not what you wanted. The keyword DISTINCT removes these duplicates:
SELECT DISTINCT ville FROM clients;
Now the database returns each city once: Dijon, Lyon, Paris. Three rows, not fifty.
DISTINCT on multiple columns: it is the combination that is unique. SELECT DISTINCT ville, categorie FROM commandes does not look for unique cities AND unique categories separately. It looks for unique (ville, categorie) pairs. If Dijon + informatique appears three times and Dijon + maison twice, you get two rows: one for each distinct pair. This often catches people off guard at first.
ORDER BY and LIMIT: sort and limit
ORDER BY sorts the result. ASC = ascending (default), DESC = descending.
We want to retrieve the 3 most expensive products from the produits table. A colleague writes: SELECT * FROM produits LIMIT 3. Before reading on: does this query return the 3 most expensive products? Why? What needs to be added?
See the answer
No. LIMIT 3 simply returns 3 rows, but without ORDER BY the row order is not guaranteed: the database returns them in an arbitrary order (often insertion order, but nothing enforces that). You therefore get 3 random products, not the most expensive ones. For the "top 3", you must sort first, then limit: SELECT * FROM produits ORDER BY prix DESC LIMIT 3. ORDER BY prix DESC ranks from most to least expensive, and LIMIT 3 keeps only the first 3 rows of that ranked result. The logical order: sort first, then cut.
SELECT nom, prix
FROM produits
ORDER BY prix DESC;
LIMIT caps the result to a number of rows. The boss's request — the 5 most expensive products — becomes:
SELECT nom, prix
FROM produits
ORDER BY prix DESC
LIMIT 5;
The clause order is always the same: SELECT → FROM → WHERE → ORDER BY → LIMIT. If you reverse it, the query fails.
To paginate (page 2, 10 per page), add OFFSET: LIMIT 10 OFFSET 10 skips the first 10 rows and returns the next 10.
Without ORDER BY, no order is guaranteed. The DBMS is free to return rows in whatever order suits it (insertion, internal storage, execution plan). Even if the result looks sorted, it is by accident: never rely on it. Whenever order matters, state it explicitly with ORDER BY.
À vous d'essayer, la base est déjà remplie. Avant de cliquer sur Exécuter, prédisez : combien de villes distinctes vont sortir, et lesquelles ? Lancez ensuite, puis modifiez la requête pour tester SELECT ville (sans DISTINCT) et observez la différence.
CREATE TABLE clients (id INTEGER, nom TEXT, email TEXT, ville TEXT);
INSERT INTO clients VALUES (1, 'Alice Durand', 'alice@exemple.fr', 'Dijon');
INSERT INTO clients VALUES (2, 'Marc Petit', 'marc@exemple.fr', 'Lyon');
INSERT INTO clients VALUES (3, 'Léa Martin', 'lea@exemple.fr', 'Dijon');
SELECT DISTINCT ville
FROM clients
ORDER BY ville;
🎯 Pratique
S'entraîner (clique pour ouvrir) :
✨ Prompt IA
Demandez la requête à l'IA en lui donnant le schéma, puis vérifiez qu'elle nomme bien les colonnes au lieu d'un SELECT * :
J'ai une table produits avec les colonnes : id, nom, categorie, prix, stock. Écris une requête SQL qui renvoie le nom et le prix des 5 produits les plus chers de la catégorie informatique. Nomme les colonnes explicitement (pas de SELECT *) et explique chaque clause.
💬 Ré-explique sans regarder
Sans relire la réponse de l'IA : avec tes mots, pourquoi vaut-il mieux écrire SELECT nom, prix plutôt que SELECT * quand tu ne veux que ces deux colonnes ?
SELECT * renverrait soudain une colonne en plus ou dans un ordre différent et casserait le code qui lit par position ; et la requête documente clairement ce dont l'application a besoin.Écrivez une requête qui renvoie le nom et le prix des produits de la table produits, triés du moins cher au plus cher, limités à 3 résultats. Utilisez SELECT, FROM, ORDER BY et LIMIT.
⚖️ Juge le code de l'IA
Tu as demandé à l'IA « le nom et le prix des 3 produits les plus chers ». Elle te propose cette requête. Ton rôle de relecteur : l'accepter telle quelle ou la rejeter, et dire pourquoi.
SELECT *
FROM produits
ORDER BY prix DESC
LIMIT 3;
LIMIT 3 sont justes, mais tu avais demandé le nom et le prix, et l'IA renvoie SELECT * : toutes les colonnes (id, categorie, stock comprises). C'est plus de données que nécessaire, et surtout c'est fragile : si demain on ajoute une colonne à la table, le résultat change tout seul. Corrige en SELECT nom, prix.🧠 Rappel libre
Sans remonter dans la leçon : écris de mémoire la requête qui renvoie le nom et le prix des 5 produits les plus chers de la table produits. Dans quel ordre s'enchaînent les clauses ?
SELECT nom, prix FROM produits ORDER BY prix DESC LIMIT 5; : l'ordre des clauses est toujours SELECT → FROM → (WHERE) → ORDER BY → LIMIT. DESC trie du plus cher au moins cher, et LIMIT 5 ne garde que les 5 premières lignes du résultat trié. Inverser cet ordre fait échouer la requête.SELECT DISTINCT ville, pays FROM clients. Qu'est-ce que DISTINCT rend unique ici ?Vous savez lire, trier, limiter et dédoublonner les résultats. Mais on veut rarement tout : la prochaine leçon ajoute le filtre WHERE (AND, OR, LIKE, IN, BETWEEN) et le tri multi-colonnes pour ne garder que les lignes utiles.
Leçon 3 : Filtrer et trier →