OUJOOD.COM
Quand on travaille avec plusieurs tables MySQL, les jointures SQL deviennent vite indispensables. Ce tutoriel couvre les cinq types de jointures — INNER JOIN, LEFT JOIN, RIGHT JOIN, FULL OUTER JOIN simulé et CROSS JOIN — avec des exemples concrets exécutés depuis Node.js. On commence avec le module classique mysql, puis on bascule sur mysql2 et ses Promises pour un code plus moderne.
Créer les tables de test
Pour tous les exemples qui suivent, on utilise deux tables simples : members (membres) et committees (comités). Certains noms apparaissent dans les deux tables, d'autres dans une seule — ce qui rend les différences entre les jointures bien visibles.
CREATE TABLE members (
member_id INT AUTO_INCREMENT,
name VARCHAR(100),
PRIMARY KEY (member_id)
);
INSERT INTO members(name)
VALUES('John'), ('Jane'), ('Mary'), ('David'), ('Amelia');
CREATE TABLE members: crée la table avec deux colonnes,member_idetname.AUTO_INCREMENT: chaque nouveau membre reçoit automatiquement un identifiant unique.INSERT INTO members: insère cinq membres d'un coup avec une seule requête.
CREATE TABLE committees (
committee_id INT AUTO_INCREMENT,
name VARCHAR(100),
PRIMARY KEY (committee_id)
);
INSERT INTO committees(name)
VALUES('Joe'), ('Sarah'), ('Amelia'), ('David');
CREATE TABLE committees: même structure quemembers, aveccommittee_idà la place demember_id.- Seuls Amelia et David sont présents dans les deux tables — les autres noms sont exclusifs à l'une ou l'autre.
LEFT JOIN : tous les membres, avec ou sans comité
Le LEFT JOIN retourne toutes les lignes de la table de gauche (members), plus les correspondances trouvées dans la table de droite (committees). Si un membre n'a pas de comité associé, ses colonnes côté committees affichent NULL.
Requête SQL
SELECT m.member_id, m.name AS member, c.committee_id, c.name AS committee FROM members m LEFT JOIN committees c ON c.name = m.name;
FROM members m: la table de gauche, qui pilote les résultats — toutes ses lignes seront présentes.LEFT JOIN committees c ON c.name = m.name: pour chaque membre, MySQL cherche un comité portant le même nom. S'il n'en trouve pas, les colonnes decommitteesvalentNULL.
Avec Node.js — module mysql
Voici comment exécuter ce LEFT JOIN depuis Node.js avec le module mysql classique (callback-based).
const mysql = require('mysql');
// Paramètres de connexion à votre base MySQL
const con = mysql.createConnection({
host: "localhost",
user: "root",
password: "votre_mot_de_passe",
database: "votre_base_de_donnees"
});
const qry = `
SELECT
m.member_id,
m.name AS member,
c.committee_id,
c.name AS committee
FROM
members m
LEFT JOIN committees c ON c.name = m.name;
`;
con.connect(function(err) {
if (err) throw err;
con.query(qry, function (err, results) {
if (err) throw err;
results.forEach((row) => {
console.log(JSON.stringify(row));
});
});
con.end();
});
require('mysql'): importe le module de connexion MySQL pour Node.js.createConnection: définit les paramètres de connexion (hôte, utilisateur, mot de passe, base).con.query: envoie la requête et traite les résultats dans le callback.
Résultat attendu
| member_id | member | committee_id | committee |
|---|---|---|---|
| 1 | John | NULL | NULL |
| 2 | Jane | NULL | NULL |
| 3 | Mary | NULL | NULL |
| 4 | David | 4 | David |
| 5 | Amelia | 3 | Amelia |
John, Jane et Mary n'apparaissent pas dans committees, donc leurs colonnes côté comité sont à NULL. David et Amelia existent dans les deux tables — leurs lignes sont complètes.
LEFT JOIN avec mysql2 et async/await
Le module mysql2 est l'évolution naturelle de mysql. Sa compatibilité avec les Promises permet d'écrire un code asynchrone plus lisible, sans callbacks imbriqués. Pour l'installer :
npm install mysql2
Ensuite, le même LEFT JOIN s'écrit ainsi avec mysql2/promise :
const mysql = require('mysql2/promise');
(async () => {
const connection = await mysql.createConnection({
host: "localhost",
user: "root",
password: "votre_mot_de_passe",
database: "votre_base_de_donnees"
});
try {
// execute() prépare la requête avant de l'envoyer — plus sûr que query()
const [rows] = await connection.execute(`
SELECT
m.member_id,
m.name AS member,
c.committee_id,
c.name AS committee
FROM
members m
LEFT JOIN committees c ON c.name = m.name;
`);
rows.forEach((row) => {
console.log(JSON.stringify(row));
});
} catch (error) {
console.error("Erreur :", error);
} finally {
// finally garantit que la connexion se ferme même en cas d'erreur
await connection.end();
}
})();
require('mysql2/promise'): importe la version Promise du module.connection.execute: prépare et exécute la requête en une seule étape, plus sûr quequery()contre les injections SQL.try-catch-finally: la connexion se ferme dans le blocfinally, que la requête ait réussi ou échoué.
RIGHT JOIN : tous les comités, avec ou sans membre
Le RIGHT JOIN inverse la logique : cette fois, c'est la table de droite (committees) qui pilote les résultats. Toutes ses lignes apparaissent dans la sortie, même si elles n'ont pas de correspondance dans members.
Requête SQL
SELECT m.member_id, m.name AS member, c.committee_id, c.name AS committee FROM members m RIGHT JOIN committees c ON c.name = m.name;
RIGHT JOIN committees c: inclut toutes les lignes decommittees, même celles sans membre associé.- Là où aucun membre ne correspond, les colonnes de
membersvalentNULL.
Avec Node.js et mysql2
const mysql = require('mysql2/promise');
(async () => {
const connection = await mysql.createConnection({
host: "localhost",
user: "root",
password: "votre_mot_de_passe",
database: "votre_base_de_donnees"
});
try {
const [rows] = await connection.execute(`
SELECT
m.member_id,
m.name AS member,
c.committee_id,
c.name AS committee
FROM
members m
RIGHT JOIN committees c ON c.name = m.name;
`);
rows.forEach((row) => {
console.log(JSON.stringify(row));
});
} catch (error) {
console.error("Erreur :", error);
} finally {
await connection.end();
}
})();
Résultat attendu
| member_id | member | committee_id | committee |
|---|---|---|---|
| NULL | NULL | 1 | Joe |
| NULL | NULL | 2 | Sarah |
| 5 | Amelia | 3 | Amelia |
| 4 | David | 4 | David |
Joe et Sarah n'existent que dans committees — leurs colonnes côté membres restent à NULL. Amelia et David sont dans les deux tables et s'affichent complets.
INNER JOIN : uniquement les correspondances
L'INNER JOIN est le plus restrictif des quatre : il ne retourne que les lignes qui ont une correspondance dans les deux tables simultanément. Pas de NULL, pas de lignes orphelines.
Requête SQL
SELECT m.member_id, m.name AS member, c.committee_id, c.name AS committee FROM members m INNER JOIN committees c ON c.name = m.name;
INNER JOIN committees c ON c.name = m.name: seuls les noms présents dans les deux tables passent le filtre.
Avec Node.js et mysql2
const mysql = require('mysql2/promise');
(async () => {
const connection = await mysql.createConnection({
host: "localhost",
user: "root",
password: "votre_mot_de_passe",
database: "votre_base_de_donnees"
});
try {
const [rows] = await connection.execute(`
SELECT
m.member_id,
m.name AS member,
c.committee_id,
c.name AS committee
FROM
members m
INNER JOIN committees c ON c.name = m.name;
`);
rows.forEach((row) => {
console.log(JSON.stringify(row));
});
} catch (error) {
console.error("Erreur :", error);
} finally {
await connection.end();
}
})();
Résultat attendu
| member_id | member | committee_id | committee |
|---|---|---|---|
| 4 | David | 4 | David |
| 5 | Amelia | 3 | Amelia |
Deux lignes seulement — David et Amelia — parce que ce sont les seuls noms communs aux deux tables.
FULL OUTER JOIN simulé : toutes les lignes, des deux côtés
MySQL ne dispose pas d'un mot-clé FULL OUTER JOIN natif. On le simule en combinant un LEFT JOIN et un RIGHT JOIN via UNION, ce qui déduplique les lignes communes et conserve toutes les lignes orphelines des deux tables.
Requête SQL
SELECT m.member_id, m.name AS member, c.committee_id, c.name AS committee FROM members m LEFT JOIN committees c ON c.name = m.name UNION SELECT m.member_id, m.name AS member, c.committee_id, c.name AS committee FROM members m RIGHT JOIN committees c ON c.name = m.name;
- La première
SELECT(LEFT JOIN) retourne tous les membres, avec ou sans comité. - La seconde
SELECT(RIGHT JOIN) retourne tous les comités, avec ou sans membre. UNIONfusionne les deux résultats en supprimant les doublons automatiquement.
Avec Node.js et mysql2
const mysql = require('mysql2/promise');
(async () => {
const connection = await mysql.createConnection({
host: "localhost",
user: "root",
password: "votre_mot_de_passe",
database: "votre_base_de_donnees"
});
try {
const [rows] = await connection.execute(`
SELECT
m.member_id,
m.name AS member,
c.committee_id,
c.name AS committee
FROM
members m
LEFT JOIN committees c ON c.name = m.name
UNION
SELECT
m.member_id,
m.name AS member,
c.committee_id,
c.name AS committee
FROM
members m
RIGHT JOIN committees c ON c.name = m.name;
`);
rows.forEach((row) => {
console.log(JSON.stringify(row));
});
} catch (error) {
console.error("Erreur :", error);
} finally {
await connection.end();
}
})();
Résultat attendu
| member_id | member | committee_id | committee |
|---|---|---|---|
| 1 | John | NULL | NULL |
| 2 | Jane | NULL | NULL |
| 3 | Mary | NULL | NULL |
| 4 | David | 4 | David |
| 5 | Amelia | 3 | Amelia |
| NULL | NULL | 1 | Joe |
| NULL | NULL | 2 | Sarah |
Sept lignes en tout : les cinq membres (dont trois sans comité) et les deux comités (Joe, Sarah) qui n'ont pas de membre associé.
CROSS JOIN : toutes les combinaisons possibles
Le CROSS JOIN produit le produit cartésien des deux tables — chaque ligne de members est combinée avec chaque ligne de committees. Avec 5 membres et 4 comités, on obtient 20 lignes. C'est rarement ce qu'on veut en production, mais utile pour générer des matrices ou tester des scénarios exhaustifs.
Requête SQL
SELECT m.member_id, m.name AS member, c.committee_id, c.name AS committee FROM members m CROSS JOIN committees c;
CROSS JOIN: pas de conditionON— toutes les associations membre × comité sont générées.
Avec Node.js et mysql2
const mysql = require('mysql2/promise');
(async () => {
const connection = await mysql.createConnection({
host: "localhost",
user: "root",
password: "votre_mot_de_passe",
database: "votre_base_de_donnees"
});
try {
const [rows] = await connection.execute(`
SELECT
m.member_id,
m.name AS member,
c.committee_id,
c.name AS committee
FROM
members m
CROSS JOIN committees c;
`);
rows.forEach((row) => {
console.log(JSON.stringify(row));
});
} catch (error) {
console.error("Erreur :", error);
} finally {
await connection.end();
}
})();
Extrait du résultat (20 lignes au total)
| member_id | member | committee_id | committee |
|---|---|---|---|
| 1 | John | 1 | Joe |
| 1 | John | 2 | Sarah |
| 1 | John | 3 | Amelia |
| 1 | John | 4 | David |
| … | … | … | … |
Quelle jointure utiliser et dans quel cas ?
Voici un tableau récapitulatif pour choisir rapidement la bonne jointure selon votre besoin.
| Jointure | Ce qu'elle retourne | Cas d'usage typique |
|---|---|---|
| INNER JOIN | Uniquement les lignes présentes dans les deux tables | Lister les membres qui font partie d'un comité — sans lignes incomplètes |
| LEFT JOIN | Toutes les lignes de gauche + correspondances de droite (NULL si absent) |
Lister tous les membres, y compris ceux sans comité |
| RIGHT JOIN | Toutes les lignes de droite + correspondances de gauche (NULL si absent) |
Lister tous les comités, même ceux sans membres inscrits |
| FULL OUTER JOIN (simulé) | Toutes les lignes des deux tables, correspondances ou non | Obtenir une vue complète : membres sans comité et comités sans membres |
| CROSS JOIN | Toutes les combinaisons possibles entre les deux tables | Générer une matrice exhaustive — rarement utilisé en production |
👉 Retrouvez d'autres tutoriels Node.js ici : Tutoriels Node.js
Par carabde | Mis à jour le 13 mai 2026