%% nav-debut : généré par gen_navigation.py, ne pas modifier à la main %%
> [!nav]
> ↩ [[Code et Développement/Développement d'Applications/SQL IV/SQL IV|Accueil · SQL IV]]
>
> | [[Code et Développement/Développement d'Applications/SQL IV/01_Supprimer les doublons - DISTINCT\|← Supprimer les doublons : DISTINCT]] | [[Code et Développement/Développement d'Applications/SQL IV/03_Combiner deux résultats - UNION\|Combiner deux résultats : UNION →]] |
> |:---|---:|
%% nav-fin %%
[[Code et Développement/Développement d'Applications/SQL IV/01_Supprimer les doublons - DISTINCT|Supprimer les doublons - DISTINCT]]
# Garder les premières lignes : `LIMIT`
## Introduction
« Les 3 meilleures ventes », « le client le plus fidèle », « les 10 dernières commandes »… Beaucoup de demandes ne portent que sur **les premières lignes** d'un classement. Le mot clé `LIMIT` permet de ne garder que ces lignes.
### Objectifs du chapitre
À la fin de ce chapitre, vous serez capable de :
- Limiter le nombre de lignes d'un résultat avec `LIMIT`.
- Comprendre pourquoi `LIMIT` va (presque) toujours avec `ORDER BY`.
- Repérer le piège des **ex æquo**.
Nous utilisons les tables *Clients* et *Commandes* présentées au chapitre [[Code et Développement/Développement d'Applications/SQL IV/01_Supprimer les doublons - DISTINCT|Supprimer les doublons : DISTINCT]].
---
## 1. Syntaxe
`LIMIT` s'écrit **à la toute fin** de la requête, après le `ORDER BY` :
```sql
SELECT ...
FROM ...
ORDER BY ...
LIMIT n;
```
`n` est le nombre de lignes à garder.
---
## 2. Exemple : les 3 commandes les plus chères
On nous demande : ***quelles sont les 3 commandes les plus chères ?***
### Ce que vous savez déjà faire (SQL I)
On trie les commandes par montant décroissant, puis on lit les 3 premières lignes du résultat :
```sql
SELECT id_commande, montant_total
FROM Commandes
ORDER BY montant_total DESC;
```
Cela fonctionne, mais le résultat contient **toutes** les commandes : ici 7, dans une vraie base des milliers. C'est à vous de repérer les 3 premières, et ce résultat ne peut pas être réutilisé tel quel (dans une autre requête, un tableau de bord…).
### Une autre solution : `LIMIT`
On ajoute `LIMIT 3` pour que la requête ne renvoie **que** les 3 premières lignes :
```sql
SELECT id_commande, montant_total
FROM Commandes
ORDER BY montant_total DESC
LIMIT 3;
```
### Résultat après le `ORDER BY`
Les 7 commandes sont triées par montant décroissant :
| id_commande | montant_total |
| ----------- | ------------- |
| 103 | 560.00 |
| 107 | 400.00 |
| 105 | 310.00 |
| 101 | 250.00 |
| 106 | 150.00 |
| 102 | 120.00 |
| 104 | 80.00 |
### Résultat après le `LIMIT`
`LIMIT 3` ne garde que les 3 premières lignes ; les autres disparaissent :
| id_commande | montant_total |
| ----------- | ------------- |
| 103 | 560.00 |
| 107 | 400.00 |
| 105 | 310.00 |
| <em style="color:red;text-decoration: line-through;">101</em> | <em style="color:red;text-decoration: line-through;">250.00</em> |
| <em style="color:red;text-decoration: line-through;">106</em> | <em style="color:red;text-decoration: line-through;">150.00</em> |
| <em style="color:red;text-decoration: line-through;">102</em> | <em style="color:red;text-decoration: line-through;">120.00</em> |
| <em style="color:red;text-decoration: line-through;">104</em> | <em style="color:red;text-decoration: line-through;">80.00</em> |
---
## 3. `LIMIT` sans `ORDER BY` : un résultat au hasard
> [!warning] Toujours trier avant de limiter
> Sans `ORDER BY`, l'ordre des lignes d'un résultat **n'est pas garanti**. `LIMIT 3` garde alors 3 lignes quelconques, et ce ne seront pas forcément les mêmes d'une fois à l'autre.
>
> ```sql
> SELECT id_commande, montant_total
> FROM Commandes
> LIMIT 3; -- 3 commandes, mais lesquelles ?
> ```
>
> Dès que la demande contient « les premiers », « les plus », « les moins », « les derniers », il faut un `ORDER BY` avant le `LIMIT`.
---
## 4. Sauter des lignes : `OFFSET`
On peut aussi demander à sauter les premières lignes avec `OFFSET`. Par exemple, pour obtenir les commandes classées de la 4ᵉ à la 6ᵉ place :
```sql
SELECT id_commande, montant_total
FROM Commandes
ORDER BY montant_total DESC
LIMIT 3 OFFSET 3;
```
| id_commande | montant_total |
| ----------- | ------------- |
| 101 | 250.00 |
| 106 | 150.00 |
| 102 | 120.00 |
`OFFSET 3` saute les 3 premières lignes, puis `LIMIT 3` garde les 3 suivantes. C'est ce que font les sites web qui affichent les résultats « page par page ».
---
## 5. Le piège des ex æquo
On nous demande : ***quel est le client (parmi ceux qui ont commandé) qui a passé le moins de commandes ?***
Une idée naturelle : compter les commandes de chaque client, trier par ordre croissant et garder la première ligne.
```sql
SELECT C.nom_client, COUNT(*) AS nb_commandes
FROM Clients C INNER JOIN Commandes Co ON C.id_client = Co.id_client
GROUP BY C.id_client, C.nom_client
ORDER BY nb_commandes ASC
LIMIT 1;
```
Regardons le résultat **avant** le `LIMIT` :
| nom_client | nb_commandes |
| ---------- | ------------ |
| Bernard | 1 |
| Petit | 1 |
| Martin | 2 |
| Dupont | 3 |
Bernard et Petit sont **ex æquo** avec une seule commande. Le `LIMIT 1` n'en garde qu'un, et on ne sait même pas lequel : Bernard et Petit ont la même valeur de tri, leur ordre n'est donc pas garanti.
> [!warning] `LIMIT` ne connaît pas les ex æquo
> `LIMIT n` garde **exactement n lignes**, même si la ligne suivante a la même valeur que la dernière gardée.
> - Si la demande est « **le** client qui… » ou « **les** 3 meilleurs… », demandez-vous : *que se passe-t-il s'il y a des ex æquo ?*
> - Pour obtenir **tous** les ex æquo, il faut calculer le minimum avec une sous-requête, puis garder les clients qui l'atteignent. Vous savez déjà le faire avec une sous-requête dans le `FROM` (SQL III) ; nous verrons cette solution, puis une autre, au chapitre [[Code et Développement/Développement d'Applications/SQL IV/06_Sous-requête renvoyant une valeur|Sous-requête renvoyant une valeur]].
> - Pour « **les 3** meilleurs » avec leurs ex æquo, la fonction `RANK` sera la solution : voir le chapitre [[Code et Développement/Développement d'Applications/SQL IV/11_Classer - RANK|Classer : RANK, DENSE_RANK, ROW_NUMBER]].
> [!tip] Quand `LIMIT` suffit
> `LIMIT` est parfait quand la demande porte vraiment sur un **nombre de lignes** (« affichez les 10 dernières commandes ») ou quand on sait qu'il ne peut pas y avoir d'ex æquo (tri sur un identifiant, par exemple).
> Pour rendre le résultat toujours identique, on peut ajouter un second critère de tri : `ORDER BY nb_commandes ASC, C.nom_client ASC`. Mais attention : on aura toujours **un seul** des ex æquo.
---
## 6. L'ordre d'exécution complet
`LIMIT` est la **dernière** étape exécutée : on ne peut garder « les premières lignes » qu'une fois le résultat trié.
1. `FROM`
2. `WHERE`
3. `GROUP BY`
4. `HAVING`
5. `SELECT`
6. `DISTINCT`
7. `ORDER BY`
8. **`LIMIT`**
C'est l'ordre complet utilisé dans tout SQL IV. Les fonctions de fenêtre (chapitre [[Code et Développement/Développement d'Applications/SQL IV/10_Calculer sur un groupe - PARTITION BY|Calculer sur un groupe : PARTITION BY]]) sont calculées à l'étape 5, avec le `SELECT`.
> [!note] Ordre d'écriture
> L'ordre d'écriture est : `SELECT` (avec `DISTINCT`) → `FROM` → `WHERE` → `GROUP BY` → `HAVING` → `ORDER BY` → `LIMIT`.
---
> [!important] Ce qu'il faut retenir
> - `LIMIT n` garde les `n` premières lignes du résultat ; c'est la dernière étape exécutée.
> - Sans `ORDER BY`, les lignes gardées sont imprévisibles : **on trie toujours avant de limiter**.
> - `OFFSET` permet de sauter des lignes.
> - `LIMIT` ignore les ex æquo : pour « le plus… » ou « le moins… », pensez toujours aux égalités.
Prochaine étape, mettre deux résultats l'un sous l'autre :
[[Code et Développement/Développement d'Applications/SQL IV/03_Combiner deux résultats - UNION|Combiner deux résultats : UNION]]
%% nav-debut : généré par gen_navigation.py, ne pas modifier à la main %%
> [!nav]
> ↩ [[Code et Développement/Développement d'Applications/SQL IV/SQL IV|Accueil · SQL IV]]
>
> | [[Code et Développement/Développement d'Applications/SQL IV/01_Supprimer les doublons - DISTINCT\|← Supprimer les doublons : DISTINCT]] | [[Code et Développement/Développement d'Applications/SQL IV/03_Combiner deux résultats - UNION\|Combiner deux résultats : UNION →]] |
> |:---|---:|
%% nav-fin %%
---
🗓️ Historique
Dernière mise à jour : `30 octobre 2026`
Rédigé par : [[Vincent TELLIER]]