880 Stimmen

Wie kann ich einen FULL OUTER JOIN in MySQL durchführen?

Ich möchte eine [vollständige äußere Verknüpfung](https://en.wikipedia.org/wiki/Join(SQL)#Full_outerjoin) in MySQL. Ist dies möglich? Ist eine vollständige äußere Verknüpfung von MySQL unterstützt?

4 Stimmen

4 Stimmen

Auf diese Frage gibt es bessere Antworten

6 Stimmen

Achten Sie auf die Antworten hier. Der SQL-Standard besagt, dass full join on inner join on rows union all unmatched left table rows extended by nulls union all right table rows extended by nulls ist. Die meisten Antworten hier sind falsch (siehe die Kommentare) & die, die nicht falsch sind, behandeln den allgemeinen Fall nicht. Auch wenn es viele (ungerechtfertigte) Upvotes gibt. (Siehe meine Antwort.)

-3voto

Rubén Ruíz Punkte 367

Ich korrigiere die Antwort, und die Arbeiten umfassen alle Zeilen (auf der Grundlage der Antwort von Pavle Lekic):

    (
    SELECT a.* FROM tablea a
    LEFT JOIN tableb b ON a.`key` = b.key
    WHERE b.`key` is null
    )
    UNION ALL
    (
    SELECT a.* FROM tablea a
    LEFT JOIN tableb b ON a.`key` = b.key
    where  a.`key` = b.`key`
    )
    UNION ALL
    (
    SELECT b.* FROM tablea a
    right JOIN tableb b ON b.`key` = a.key
    WHERE a.`key` is null
    );

1 Stimmen

Nein, dies ist eine Art von "outer-only"-Join, der nur die Zeilen aus tablea die keine Entsprechung in tableb und vice versa. Die Sie versuchen UNION ALL was nur funktionieren würde, wenn diese beiden Tabellen gleich geordnete Spalten haben, was nicht garantiert ist.

0 Stimmen

Es funktioniert, ich erstelle auf temp Datenbank tablea(1,2,3,4,5,6) und tableb(4,5,6,7,8,9) seine Zeilen haben 3 Spalten "id", "number" und "name_number" als Text, und arbeitet in Ergebnis nur haben (1,2,3,7,8,9)

2 Stimmen

Das ist keine äußere Verknüpfung. Eine äußere Verknüpfung umfasst auch die übereinstimmenden Mitglieder.

-4voto

Super Mario Punkte 838

Verwenden Sie eine Kreuzverbindung Lösung:

SELECT t1.*, t2.*
FROM table1 t1
INNER JOIN table2 t2 
ON 1=1;

4 Stimmen

Nein, das ist eine Kreuzverbindung. Es wird jede Zeile in t1 mit jeder Zeile in t2 abgeglichen, was die Menge aller möglichen Kombinationen ergibt, mit select (select count(*) from t1) * (select count(*) from t2)) Zeilen in der Ergebnismenge.

1 Stimmen

Dieser Code kann zwar die Frage beantworten, aber er liefert zusätzliche Informationen über wie y warum die Lösung des Problems würde den langfristigen Wert der Antwort verbessern.

1 Stimmen

Welcher Zusatz könnte hilfreich sein? vielleicht ein Beispiel?

-5voto

Angelos Punkte 1496

Verwendung:

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

Sie kann wie folgt nachgebildet werden:

 SELECT t1.*, t2.*
 FROM (SELECT * FROM t1 UNION SELECT name FROM t2) tmp
 LEFT JOIN t1 ON t1.id = tmp.id
 LEFT JOIN t2 ON t2.id = tmp.id;

Die Verwendung einer UNION- oder UNION ALL-Antwort deckt nicht den Grenzfall ab, in dem die Basistabellen doppelte Einträge haben.

Erläuterung:

Es gibt einen Grenzfall, den eine UNION oder UNION ALL nicht abdecken kann. Wir können dies nicht mit MySQL testen, da es keine Full Outer Joins unterstützt, aber wir können dies mit einer Datenbank veranschaulichen, die es unterstützt:

 WITH cte_t1 AS
 (
     SELECT 1 AS id1
     UNION ALL SELECT 2
     UNION ALL SELECT 5
     UNION ALL SELECT 6
     UNION ALL SELECT 6
 ),
cte_t2 AS
(
     SELECT 3 AS id2
     UNION ALL SELECT 4
     UNION ALL SELECT 5
     UNION ALL SELECT 6
     UNION ALL SELECT 6
)
SELECT  *  FROM  cte_t1 t1 FULL OUTER JOIN cte_t2 t2 ON t1.id1 = t2.id2;

This gives us this answer:

id1  id2
1  NULL
2  NULL
NULL  3
NULL  4
5  5
6  6
6  6
6  6
6  6

Die UNION-Lösung:

SELECT  * FROM  cte_t1 t1 LEFT OUTER JOIN cte_t2 t2 ON t1.id1 = t2.id2
UNION    
SELECT  * FROM cte_t1 t1 RIGHT OUTER JOIN cte_t2 t2 ON t1.id1 = t2.id2

Gibt eine falsche Antwort:

 id1  id2
NULL  3
NULL  4
1  NULL
2  NULL
5  5
6  6

Die UNION ALL-Lösung:

SELECT  * FROM cte_t1 t1 LEFT OUTER join cte_t2 t2 ON t1.id1 = t2.id2
UNION ALL
SELECT  * FROM  cte_t1 t1 RIGHT OUTER JOIN cte_t2 t2 ON t1.id1 = t2.id2

ist ebenfalls falsch.

id1  id2
1  NULL
2  NULL
5  5
6  6
6  6
6  6
6  6
NULL  3
NULL  4
5  5
6  6
6  6
6  6
6  6

Während diese Abfrage:

SELECT t1.*, t2.*
FROM (SELECT * FROM t1 UNION SELECT name FROM t2) tmp
LEFT JOIN t1 ON t1.id = tmp.id
LEFT JOIN t2 ON t2.id = tmp.id;

Gibt das Folgende an:

id1  id2
1  NULL
2  NULL
NULL  3
NULL  4
5  5
6  6
6  6
6  6
6  6

Die Reihenfolge ist anders, aber ansonsten stimmt sie mit der richtigen Antwort überein.

0 Stimmen

Das ist niedlich, stellt aber die Situation falsch dar. UNION ALL Lösung. Außerdem wird eine Lösung vorgestellt, die UNION was bei großen Quelltabellen wegen der erforderlichen Deduplizierung langsamer wäre. Schließlich würde es nicht kompiliert werden, weil das Feld id in der Unterabfrage nicht vorhanden ist tmp .

0 Stimmen

Ich habe nie eine Behauptung über die Geschwindigkeit aufgestellt, und auch der Auftraggeber hat nichts über die Geschwindigkeit gesagt. Angenommen, die UNION ALL (Sie geben nicht an, welche) und die UNION ALL geben beide die richtige Antwort, dann müssten wir, wenn wir die Behauptung aufstellen wollten, dass eine der beiden schneller ist, Benchmarks vorlegen, und das wäre ein Abschweifen von der Frage des Auftraggebers.

0 Stimmen

Was die Bemerkung betrifft, dass die ID nicht in der Unterabfrage enthalten ist, so habe ich den Tippfehler korrigiert - danke für den Hinweis. Ihre Behauptung über falsche Darstellungen ist vage - wenn Sie vielleicht mehr Informationen liefern könnten, kann ich darauf eingehen. Zu Ihrer letzten Bemerkung über die Niedlichkeit: Ich habe keine

-7voto

alamelu Punkte 286

Es ist auch möglich, aber Sie müssen die gleichen Feldnamen in select angeben.

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

1 Stimmen

Dies ist nur eine Duplizierung der Ergebnisse aus einer linken Verknüpfung.

1 Stimmen

Dies führt nicht zu einem gleichwertigen Ergebnis wie eine vollständige äußere Verknüpfung.

-9voto

philipxy Punkte 14320

Der SQL-Standard besagt full join on es inner join on Zeilen union all nicht übereinstimmende linke Tabellenzeilen, erweitert um Nullen union all rechte Tabellenzeilen um Nullen erweitert. D.h. inner join on Zeilen union all Reihen in left join on aber nicht inner join on union all Reihen in right join on aber nicht inner join on .

Ie left join on Zeilen union all right join on Zeilen nicht in inner join on . Oder wenn Sie wissen, dass Ihr inner join on Ergebnis kann in einer bestimmten rechten Tabellenspalte nicht Null haben, dann " right join on Zeilen nicht in inner join on " sind Zeilen in right join on mit dem on Bedingung erweitert um and diese Spalte is null .

Ie ähnlich right join on union all geeignet. left join on Reihen.

Von Was ist der Unterschied zwischen "INNER JOIN" und "OUTER JOIN"? :

(SQL Standard 2006 SQL/Foundation 7.7 Syntaxregeln 1, Allgemeine Regeln 1 b, 3 c & d, 5 b.)

0 Stimmen

Dies scheint teilweise unverständlich zu sein (z.B., "full join on is inner join on rows union all unmatched left table rows extended by nulls union all right table rows extended by nulls." ). Können Sie das umformulieren?

0 Stimmen

@PeterMortensen Ich werde den Beitrag bald bearbeiten. FULL JOIN ON liefert <die Zeilen, die INNER JOIN ON liefert> UNION ALL <die Zeilen, die man erhält, wenn man die linken Tabellenzeilen nimmt, die nicht am INNER JOIN teilgenommen haben, und sie mit einem NULL für jede rechte Tabellenspalte erweitert> UNION ALL <die Zeilen, die man erhält, wenn man die rechten Tabellenzeilen nimmt, die nicht am INNER JOIN teilgenommen haben, und sie mit einem NULL für jede linke Tabellenspalte erweitert>. Natürlich sollte die Formulierung für jeden verständlich sein. Aber wenn Sie wissen, was FULL JOIN ON zurückgibt, finde ich es seltsam, dass Sie es nicht so analysieren können, wie es ist.

0 Stimmen

@PeterMortensen Deine Kommas haben die Bedeutung verändert, also habe ich sie zurückgenommen. Aber ich werde sie bearbeiten, um sie zu verdeutlichen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X