Leçon 7 / 8
Leçon 07 · Partie 2 — Modifier les données

JOIN — Relier des tables

Pourquoi plusieurs tables ?

Imagine une boutique en ligne. Tu as des utilisateurs et des commandes. Mauvaise idée de tout mettre dans une seule table :

-- Mauvaise approche : tout dans une table
+----+--------+------------------+----------+---------+
| id | nom    | email            | commande | montant |
+----+--------+------------------+----------+---------+
|  1 | Alice  | alice@ex.com     | Livre    |  15.00  |
|  2 | Alice  | alice@ex.com     | Stylo    |   3.50  |
|  3 | Alice  | alice@ex.com     | Cahier   |   5.00  |
+----+--------+------------------+----------+---------+
-- Problème : email d'Alice répété 3 fois → redondance

La bonne approche : deux tables séparées. On les lie avec une clé étrangère. Une clé étrangère, c'est une colonne qui contient l'ID d'un enregistrement dans une autre table.

-- Table utilisateurs
CREATE TABLE utilisateurs (
  id    INT AUTO_INCREMENT PRIMARY KEY,
  nom   VARCHAR(100),
  email VARCHAR(150)
);

-- Table commandes (liée à utilisateurs)
CREATE TABLE commandes (
  id             INT AUTO_INCREMENT PRIMARY KEY,
  utilisateur_id INT NOT NULL,        -- clé étrangère
  produit        VARCHAR(200),
  montant        DECIMAL(10,2),
  date_commande  DATETIME DEFAULT CURRENT_TIMESTAMP
);

INNER JOIN : relier les tables

INNER JOIN combine deux tables. Il retourne seulement les lignes qui ont une correspondance dans les deux. Pense à l'intersection de deux ensembles.

-- Toutes les commandes avec le nom et l'email du client
SELECT
  u.nom,
  u.email,
  c.produit,
  c.montant
FROM commandes c
INNER JOIN utilisateurs u
  ON c.utilisateur_id = u.id;
// Résultat
+--------+-------------+---------+---------+
| nom    | email       | produit | montant |
+--------+-------------+---------+---------+
| Alice  | alice@ex... | Livre   |   15.00 |
| Alice  | alice@ex... | Stylo   |    3.50 |
| Bob    | bob@ex...   | Cahier  |    5.00 |
+--------+-------------+---------+---------+

LEFT JOIN : inclure les lignes sans correspondance

-- Tous les utilisateurs, MÊME ceux sans commande
SELECT
  u.nom,
  COUNT(c.id) AS nb_commandes,
  COALESCE(SUM(c.montant), 0) AS total
FROM utilisateurs u
LEFT JOIN commandes c
  ON u.id = c.utilisateur_id
GROUP BY u.id, u.nom
ORDER BY total DESC;

JOIN avec PDO


require_once 'connexion.php';

$utilisateur_id = 1;

$stmt = $pdo->prepare("
    SELECT u.nom, c.produit, c.montant, c.date_commande
    FROM commandes c
    INNER JOIN utilisateurs u ON c.utilisateur_id = u.id
    WHERE u.id = :uid
    ORDER BY c.date_commande DESC
");

$stmt->execute([':uid' => $utilisateur_id]);
$commandes = $stmt->fetchAll(PDO::FETCH_ASSOC);
// À retenir
  • Clé étrangère = colonne qui fait référence à l'ID d'une autre table
  • INNER JOIN = seulement les lignes avec correspondance dans les deux tables
  • LEFT JOIN = toutes les lignes de la table gauche, même sans correspondance
  • Utiliser des alias de table (u, c) pour les requêtes lisibles
  • GROUP BY pour agréger des données (COUNT, SUM, AVG)
  • Ne jamais dupliquer une donnée — une info = une seule fois dans la BDD