%% 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]]