SQL IN et BETWEEN : listes et intervalles
Quand une condition WHERE commence à aligner les OR (« Lyon ou Marseille ou Nantes… ») ou à encadrer une valeur (« entre 10 et 50 »), deux opérateurs rendent la requête plus courte et plus lisible : IN et BETWEEN.
Syntaxe
WHERE colonne IN (valeur1, valeur2, …)
WHERE colonne BETWEEN minimum AND maximumComment ça marche
IN : une valeur parmi une liste
ville IN ('Lyon', 'Marseille') est strictement équivalent à ville = 'Lyon' OR ville = 'Marseille'. La liste peut contenir autant de valeurs que nécessaire, et même être remplacée par une sous-requête qui renvoie une liste.
NOT IN fait l'inverse : il garde les lignes dont la valeur n'est dans aucune des valeurs listées.
BETWEEN : un intervalle
prix BETWEEN 10 AND 50 équivaut à prix >= 10 AND prix <= 50 : les deux bornes sont incluses. Il fonctionne aussi avec des dates écrites au format AAAA-MM-JJ et avec des textes (ordre alphabétique).
Schéma
| prenom | ville |
|---|---|
| Léa | Lyon |
| Hugo | Paris |
| Adam | Nantes |
| Zoé | Lille |
| prenom | ville |
|---|---|
| Léa | Lyon |
| Adam | Nantes |
Schéma simplifié pour illustrer le principe. Les exemples ci-dessous utilisent la vraie base d'exercices de SQL Quest (une boutique en ligne fictive : voir le schéma complet).
Exemples avec leurs résultats
1. IN avec une liste de villes
Les clients de Lyon ou de Marseille.
SELECT prenom, nom, ville
FROM clients
WHERE ville IN ('Lyon', 'Marseille')
LIMIT 8; Essayer dans le bac à sable| prenom | nom | ville |
|---|---|---|
| Léa | Laurent | Marseille |
| Alice | Faure | Lyon |
| Chloé | Fontaine | Lyon |
| Yanis | Chevalier | Marseille |
| Manon | Fontaine | Marseille |
| Sarah | Michel | Lyon |
| Lucas | Martin | Marseille |
| Louis | Moreau | Marseille |
8 lignes au total
2. BETWEEN sur des prix
Les produits entre 10 et 20 €, bornes comprises.
SELECT nom, prix
FROM produits
WHERE prix BETWEEN 10 AND 20; Essayer dans le bac à sable| nom | prix |
|---|---|
| Clavier mécanique | 15 |
| Coussin | 10,86 |
| Vase céramique | 18,35 |
| Ballon de foot | 14,68 |
| Livre de cuisine | 18,67 |
5 lignes au total
3. BETWEEN sur des dates
Les commandes passées en janvier 2025.
SELECT id, date_commande, statut
FROM commandes
WHERE date_commande BETWEEN '2025-01-01' AND '2025-01-31'
LIMIT 8; Essayer dans le bac à sable| id | date_commande | statut |
|---|---|---|
| 72 | 2025-01-14 | en cours |
| 102 | 2025-01-16 | expédiée |
| 139 | 2025-01-09 | livrée |
| 225 | 2025-01-19 | expédiée |
| 248 | 2025-01-14 | livrée |
| 259 | 2025-01-01 | en cours |
| 273 | 2025-01-25 | expédiée |
| 367 | 2025-01-02 | livrée |
8 lignes au total
4. NOT IN
Les commandes qui ne sont ni livrées ni expédiées.
SELECT statut, COUNT(*) AS nb
FROM commandes
WHERE statut NOT IN ('livrée', 'expédiée')
GROUP BY statut; Essayer dans le bac à sable| statut | nb |
|---|---|
| annulée | 92 |
| en cours | 109 |
2 lignes au total
Les erreurs fréquentes
Inverser les bornes de BETWEEN
La plus petite valeur doit venir en premier. BETWEEN 50 AND 10 ne renvoie jamais rien.
SELECT * FROM produits WHERE prix BETWEEN 50 AND 10;SELECT * FROM produits WHERE prix BETWEEN 10 AND 50;Oublier les parenthèses de IN
La liste de IN doit toujours être entre parenthèses, avec des virgules.
SELECT * FROM clients WHERE ville IN 'Lyon', 'Lille';SELECT * FROM clients WHERE ville IN ('Lyon', 'Lille');NOT IN avec une valeur NULL
Si la liste (ou la sous-requête) de NOT IN contient un NULL, la condition n'est jamais vraie et la requête ne renvoie rien. Préférez NOT EXISTS avec une sous-requête.
SELECT * FROM clients WHERE age NOT IN (20, NULL);SELECT * FROM clients WHERE age NOT IN (20) AND age IS NOT NULL;Exercices
Essayez d'écrire la requête vous-même avant d'ouvrir la solution.
Défi 1. Affichez les produits des catégories « Livres » et « Alimentation ».
Voir une solution
SELECT nom, categorie, prix FROM produits WHERE categorie IN ('Livres', 'Alimentation');| nom | categorie | prix |
|---|---|---|
| Roman policier | Livres | 8,03 |
| Guide SQL | Livres | 25,25 |
| BD aventure | Livres | 9,98 |
| Livre de cuisine | Livres | 18,67 |
| Manga tome 1 | Livres | 28,92 |
| Café en grains | Alimentation | 21,79 |
| Thé vert | Alimentation | 35,83 |
| Chocolat noir | Alimentation | 22,31 |
10 lignes au total · 8 affichées
Essayer dans le bac à sableDéfi 2. Affichez les employés dont le salaire est compris entre 3 000 et 4 000 €.
Voir une solution
SELECT prenom, nom, salaire FROM employes WHERE salaire BETWEEN 3000 AND 4000;| prenom | nom | salaire |
|---|---|---|
| Nathan | Martin | 3 400 |
| Alice | Lefebvre | 3 800 |
| Hugo | Bonnet | 3 300 |
| Chloé | Blanc | 3 800 |
| Inès | Faure | 3 600 |
| Chloé | Roux | 3 600 |
| Léa | Garcia | 3 500 |
| Louis | Lambert | 3 900 |
8 lignes au total
Essayer dans le bac à sableLes exercices interactifs sont corrigés automatiquement, avec un prof qui explique vos erreurs. Une leçon résumée reste affichée à côté de l'éditeur.
Questions fréquentes
BETWEEN inclut-il les bornes ?
Oui. BETWEEN 10 AND 20 garde 10 et 20. Pour exclure une borne, utilisez > et < à la place.
IN est-il plus rapide qu'une suite de OR ?
Le résultat est identique et la plupart des bases l'exécutent de la même façon. IN est surtout plus lisible.
Peut-on mettre une requête dans IN ?
Oui : WHERE id IN (SELECT client_id FROM commandes) garde les clients qui ont passé au moins une commande. C'est une sous-requête.