892 votes

Comment puis-je faire un FULL OUTER JOIN dans MySQL ?

Je veux faire un [jointure externe complète](https://en.wikipedia.org/wiki/Join(SQL)#Full_outerjoin) dans MySQL. Est-ce possible ? Est-ce qu'un jointure externe complète supporté par MySQL ?

4 votes

4 votes

Cette question a de meilleures réponses

6 votes

Méfiez-vous des réponses ici. La norme SQL dit que la jointure complète est une jointure interne sur les rangées union de toutes les rangées de table de gauche non appariées étendues par des nuls union de toutes les rangées de table de droite étendues par des nuls. La plupart des réponses données ici sont fausses (voir les commentaires) et celles qui ne sont pas fausses ne traitent pas le cas général. Même s'il y a beaucoup de votes positifs (injustifiés). (Voir ma réponse).

896voto

Pablo Santa Cruz Points 73944

Vous n'avez pas jointures complètes dans MySQL, mais vous pouvez sûrement les imiter .

Pour un code échantillon transcrit de cette question de Stack Overflow vous avez :

Avec deux tables t1, t2 :

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id

La requête ci-dessus fonctionne pour les cas particuliers où une jointure externe complète ne produirait pas de lignes en double. La requête ci-dessus dépend de l'option UNION pour supprimer les lignes en double introduites par le motif de la requête. Nous pouvons éviter d'introduire des rangs en double en utilisant un filtre de type anti-jointure pour la seconde requête, puis utilisez un opérateur de jeu UNION ALL pour combiner les deux jeux. Dans le cas plus général où une jointure externe complète renverrait des lignes en double, nous pouvons procéder ainsi :

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION ALL
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
WHERE t1.id IS NULL

49 votes

En fait, ce que vous avez écrit n'est pas correct. Parce que lorsque vous faites un UNION, vous supprimez les doublons, et parfois lorsque vous joignez deux tables différentes, il devrait y avoir des doublons.

168 votes

C'est le bon exemple : (SELECT ... FROM tbl1 LEFT JOIN tbl2 ...) UNION ALL (SELECT ... FROM tbl1 RIGHT JOIN tbl2 ... WHERE tbl1.col IS NULL)

8 votes

La différence est que je fais une jointure inclusive à gauche et ensuite une exclusive à droite en utilisant UNION. TOUTES

452voto

Nathan Long Points 30303

La réponse qui Pablo Santa Cruz gave est correct ; toutefois, au cas où quelqu'un tomberait sur cette page et souhaiterait plus de précisions, voici une ventilation détaillée.

Exemples de tableaux

Supposons que nous ayons les tableaux suivants :

-- t1
id  name
1   Tim
2   Marta

-- t2
id  name
1   Tim
3   Katarina

Joints internes

Un joint intérieur, comme ceci :

SELECT *
FROM `t1`
INNER JOIN `t2` ON `t1`.`id` = `t2`.`id`;

Nous obtiendrions seulement les enregistrements qui apparaissent dans les deux tables, comme ceci :

1 Tim  1 Tim

Les jointures internes n'ont pas de direction (comme la gauche ou la droite) car elles sont explicitement bidirectionnelles - nous exigeons une correspondance des deux côtés.

Joints externes

Les jointures externes, quant à elles, servent à trouver des enregistrements qui n'ont peut-être pas de correspondance dans l'autre table. En tant que tel, vous devez spécifier de quel côté de la jointure est autorisé à avoir un enregistrement manquant.

LEFT JOIN y RIGHT JOIN sont des raccourcis pour LEFT OUTER JOIN y RIGHT OUTER JOIN Je vais utiliser leurs noms complets ci-dessous pour renforcer le concept de jointures externes par rapport aux jointures internes.

Jointure extérieure gauche

Une jointure externe gauche, comme ceci :

SELECT *
FROM `t1`
LEFT OUTER JOIN `t2` ON `t1`.`id` = `t2`.`id`;

...nous obtiendrait tous les enregistrements de la table de gauche, qu'ils aient ou non une correspondance dans la table de droite, comme ceci :

1 Tim   1    Tim
2 Marta NULL NULL

Jointure extérieure droite

Un joint extérieur droit, comme ceci :

SELECT *
FROM `t1`
RIGHT OUTER JOIN `t2` ON `t1`.`id` = `t2`.`id`;

...nous obtiendrait tous les enregistrements de la table de droite, qu'ils aient ou non une correspondance dans la table de gauche, comme ceci :

1    Tim   1  Tim
NULL NULL  3  Katarina

Jointure externe complète

Une jointure externe complète nous donnerait tous les enregistrements des deux tables, qu'ils aient ou non une correspondance dans l'autre table, avec des NULL des deux côtés en cas d'absence de correspondance. Le résultat ressemblerait à ceci :

1    Tim   1    Tim
2    Marta NULL NULL
NULL NULL  3    Katarina

Toutefois, comme l'a souligné Pablo Santa Cruz, MySQL ne prend pas en charge cette fonctionnalité. Nous pouvons l'émuler en faisant une UNION d'une jointure gauche et d'une jointure droite, comme ceci :

SELECT *
FROM `t1`
LEFT OUTER JOIN `t2` ON `t1`.`id` = `t2`.`id`

UNION

SELECT *
FROM `t1`
RIGHT OUTER JOIN `t2` ON `t1`.`id` = `t2`.`id`;

Vous pouvez penser à un UNION comme signifiant "exécuter ces deux requêtes, puis empiler les résultats l'un sur l'autre" ; certaines des lignes proviendront de la première requête et d'autres de la seconde.

Il convient de noter qu'un UNION dans MySQL éliminera les doublons exacts : Tim apparaîtra dans les deux requêtes ici, mais le résultat de la requête UNION ne le cite qu'une fois. Mon collègue gourou des bases de données estime qu'il ne faut pas se fier à ce comportement. Donc, pour être plus explicite à ce sujet, nous pourrions ajouter une balise WHERE à la deuxième requête :

SELECT *
FROM `t1`
LEFT OUTER JOIN `t2` ON `t1`.`id` = `t2`.`id`

UNION

SELECT *
FROM `t1`
RIGHT OUTER JOIN `t2` ON `t1`.`id` = `t2`.`id`
WHERE `t1`.`id` IS NULL;

D'autre part, si vous recherché pour voir les doublons pour une raison quelconque, vous pouvez utiliser UNION ALL .

5 votes

Pour MySQL, il faut vraiment éviter d'utiliser UNION au lieu de UNION ALL s'il n'y a pas de chevauchement (voir le commentaire de Pavle ci-dessus). Si vous pouviez ajouter des informations supplémentaires à cet effet dans votre réponse ici, je pense que ce serait la réponse préférée pour cette question car elle est plus complète.

3 votes

La recommandation du "collègue gourou des bases de données" est correcte. En termes de modèle relationnel (tout le travail théorique effectué par Ted Codd et Chris Date), une requête de la dernière forme émule un FULL OUTER JOIN, car elle combine deux ensembles distincts, La seconde requête n'introduit pas de "doublons" (des lignes déjà retournées par la première requête) qui ne seraient pas produits par un FULL OUTER JOIN . Il n'y a rien de mal à faire des requêtes de cette façon, et à utiliser UNION pour supprimer ces doublons. Mais pour vraiment répliquer une FULL OUTER JOIN nous avons besoin que l'une des requêtes soit une anti-jonction.

0 votes

L'article de Jeff Atwood explique très bien les types de jointures à l'aide de diagrammes de Venn. Il donne un exemple de l'anti-jonction... qui renvoie les lignes de A qui ne sont pas dans B. Et nous pouvons voir comment cet ensemble est distinct de l'ensemble de toutes les lignes de B et des lignes correspondantes de A.

4voto

Rami Jamleh Points 517

En SQLite, vous devez faire cela :

SELECT * 
FROM leftTable lt 
LEFT JOIN rightTable rt ON lt.id = rt.lrid 
UNION
SELECT lt.*, rl.*  -- To match column set
FROM rightTable rt 
LEFT JOIN  leftTable lt ON lt.id = rt.lrid

0 votes

Peut-on l'utiliser ? comme : SELECT * FROM leftTable lt LEFT JOIN rightTable rt ON lt.id = rt.lrid UNION SELECT lt.*, rl.* -- Pour correspondre au jeu de colonnes FROM leftTable lt RIGHT JOIN rightTable rt ON lt.id = rt.lrid ;

0 votes

Oui mais SQLite ne supporte pas les jointures droites mais oui dans MYSQL oui

3 votes

Cette réponse est erronée. Elle produit des résultats erronés dans le cas de lignes dupliquées (multisets).

-2voto

plutov.by Points 8991
SELECT
    a.name,
    b.title
FROM
    author AS a
LEFT JOIN
    book AS b
    ON a.id = b.author_id
UNION
SELECT
    a.name,
    b.title
FROM
    author AS a
RIGHT JOIN
    book AS b
    ON a.id = b.author_id

2 votes

Cette réponse est erronée. Elle produit des résultats erronés dans le cas de lignes dupliquées (multisets).

-7voto

alamelu Points 153

C'est également possible, mais vous devez mentionner les mêmes noms de champs dans la sélection.

SELECT t1.name, t2.name FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION
SELECT t1.name, t2.name FROM t2
LEFT JOIN t1 ON t1.id = t2.id

2 votes

Il s'agit simplement de dupliquer les résultats d'une jointure gauche.

2 votes

Cela ne donnera pas un résultat équivalent à une jointure externe complète.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X