🔍 SELECT — Interroger les données

Le SELECT est la commande la plus utilisée en SQL. Elle permet de lire des données depuis une ou plusieurs tables.

-- Toutes les colonnes (déconseillé en production)
SELECT * FROM produits;

-- Colonnes spécifiques
SELECT nom, prix FROM produits;

-- Colonne calculée avec alias
SELECT nom, prix, ROUND(prix * 1.2, 2) AS prix_ttc FROM produits;

-- Alias de table
SELECT p.nom, p.prix FROM produits p;

-- Constante et expression
SELECT 'Bonjour' AS message, 2 + 2 AS calcul;
En production, évitez SELECT * : cela charge des données inutiles, rend le code fragile aux changements de schéma et empêche l'optimiseur de n'utiliser que les colonnes nécessaires.

🎯 WHERE — Filtrer les lignes

La clause WHERE filtre les lignes avant tout traitement. Elle s'évalue ligne par ligne.

-- Égalité
SELECT * FROM produits WHERE categorie_id = 1;

-- Comparaison
SELECT * FROM produits WHERE prix > 100;
SELECT * FROM produits WHERE stock <= 10;
SELECT * FROM produits WHERE prix != 0;   -- ou <>

-- NULL : toujours avec IS NULL / IS NOT NULL
SELECT * FROM produits WHERE categorie_id IS NULL;
SELECT * FROM clients   WHERE ville IS NOT NULL;
WHERE col = NULL ne retourne jamais de résultat en SQL — NULL n'est pas une valeur ordinaire, c'est une absence de valeur. Utilisez toujours IS NULL.

⚙️ Opérateurs logiques et de plage

AND, OR, NOT

-- AND : les deux conditions doivent être vraies
SELECT * FROM produits WHERE prix > 50 AND stock > 10;

-- OR : au moins une condition vraie
SELECT * FROM clients WHERE ville = 'Paris' OR ville = 'Lyon';

-- NOT : inverse la condition
SELECT * FROM produits WHERE NOT categorie_id = 1;

-- Parenthèses pour clarifier l'ordre d'évaluation
SELECT * FROM produits
WHERE (prix < 20 OR prix > 500) AND stock > 0;

BETWEEN

-- BETWEEN inclut les deux bornes (équivalent à >= ET <=)
SELECT * FROM produits WHERE prix BETWEEN 20 AND 200;

-- Fonctionne aussi sur les dates
SELECT * FROM commandes
WHERE date_commande BETWEEN '2024-01-01' AND '2024-12-31';

IN

-- IN : remplace plusieurs OR
SELECT * FROM commandes
WHERE statut IN ('livree', 'expediee');

-- NOT IN
SELECT * FROM clients WHERE id NOT IN (1, 3, 5);

🔎 LIKE — Recherche par pattern

LIKE permet des recherches avec des caractères génériques.

PatternSignificationExemple
%0 ou plusieurs caractèresLIKE 'A%' → commence par A
_Exactement 1 caractèreLIKE 'A_ic' → Alice, Alic...
-- Commence par
SELECT * FROM clients WHERE nom LIKE 'A%';

-- Se termine par
SELECT * FROM clients WHERE email LIKE '%@gmail.com';

-- Contient
SELECT * FROM produits WHERE nom LIKE '%Pro%';

-- Exactement 5 caractères
SELECT * FROM produits WHERE nom LIKE '_____';

-- Insensible à la casse (avec collation _ci)
SELECT * FROM produits WHERE LOWER(nom) LIKE '%pro%';

📊 ORDER BY & LIMIT

ORDER BY

-- Tri croissant (défaut)
SELECT * FROM produits ORDER BY prix ASC;
SELECT * FROM produits ORDER BY prix;       -- identique

-- Tri décroissant
SELECT * FROM produits ORDER BY prix DESC;

-- Tri multi-colonnes
SELECT * FROM clients ORDER BY ville ASC, nom ASC;

-- Tri sur colonne calculée
SELECT nom, prix * 1.2 AS prix_ttc
FROM produits
ORDER BY prix_ttc DESC;

LIMIT et OFFSET (pagination)

-- Les 5 premiers résultats
SELECT * FROM produits ORDER BY prix DESC LIMIT 5;

-- Page 2 (10 par page) : sauter les 10 premiers
SELECT * FROM produits ORDER BY id LIMIT 10 OFFSET 10;
-- Syntaxe courte équivalente :
SELECT * FROM produits ORDER BY id LIMIT 10, 10;

-- Formule générale pour la page n (base 1) :
-- LIMIT nb_par_page OFFSET (n - 1) * nb_par_page

✂️ DISTINCT

DISTINCT élimine les doublons dans les résultats.

-- Villes uniques
SELECT DISTINCT ville FROM clients;

-- Combinaisons uniques
SELECT DISTINCT ville, statut FROM commandes
JOIN clients ON commandes.client_id = clients.id;

🧮 Fonctions scalaires utiles

-- Mathématiques
SELECT ROUND(3.14159, 2);     -- 3.14
SELECT CEIL(4.1);             -- 5
SELECT FLOOR(4.9);            -- 4
SELECT ABS(-15);              -- 15

-- Chaînes
SELECT UPPER('hello');        -- HELLO
SELECT LOWER('HELLO');        -- hello
SELECT LENGTH('MySQL');       -- 5
SELECT SUBSTRING('MySQL', 1, 3); -- MyS
SELECT CONCAT('a', 'b');     -- ab
SELECT TRIM('  espace  ');   -- 'espace'

-- Dates
SELECT NOW();                 -- 2024-01-15 10:30:00
SELECT CURDATE();             -- 2024-01-15
SELECT YEAR(NOW());           -- 2024
SELECT DATE_FORMAT(NOW(), '%d/%m/%Y'); -- 15/01/2024

-- Conditionnelle
SELECT IF(prix > 100, 'cher', 'abordable') AS gamme
FROM produits;

SELECT COALESCE(ville, 'Non renseignée') AS ville
FROM clients;