INNER JOIN ON vs WHERE-Klausel


941

Nehmen Sie der Einfachheit halber an, dass alle relevanten Felder sind NOT NULL.

Du kannst tun:

SELECT
    table1.this, table2.that, table2.somethingelse
FROM
    table1, table2
WHERE
    table1.foreignkey = table2.primarykey
    AND (some other conditions)

Oder aber:

SELECT
    table1.this, table2.that, table2.somethingelse
FROM
    table1 INNER JOIN table2
    ON table1.foreignkey = table2.primarykey
WHERE
    (some other conditions)

Arbeiten diese beiden auf die gleiche Weise MySQL?




18
Wenn ich richtig verstanden habe, ist die erste Variante die implizite ANSI SQL-89-Syntax und die zweite Variante die explizite ANSI SQL-92-Join-Syntax. Beide führen bei konformen SQL-Implementierungen zum gleichen Ergebnis und bei gut durchgeführten SQL-Implementierungen zu demselben Abfrageplan. Ich persönlich bevorzuge die SQL-89-Syntax, aber viele Leute bevorzugen die SQL-92-Syntax.
Mikko Rantalainen

11
@Hogan Ich habe auf die offiziellen Namen für verschiedene Syntaxen hingewiesen. In keiner der Antworten wurden die vollständigen Namen explizit angegeben, daher habe ich beschlossen, diese als Kommentare hinzuzufügen. Mein Kommentar beantwortete jedoch nicht die eigentliche Frage, daher fügte ich dies als Kommentar und nicht als Antwort hinzu. (Antworten mit hohen Stimmen haben Behauptungen wie "INNER JOIN ist ANSI-Syntax" und "implizite ANSI-Join-Syntax ist älter", was überhaupt nichts aussagt, da beide Syntax unterschiedliche ANSI-Syntaxen sind.)
Mikko Rantalainen

Antworten:


710

INNER JOIN ist die ANSI-Syntax, die Sie verwenden sollten.

Es wird im Allgemeinen als besser lesbar angesehen, insbesondere wenn Sie viele Tabellen verbinden.

Es kann auch leicht durch ein ersetzt werden, OUTER JOINwenn ein Bedarf entsteht.

Die WHERESyntax ist eher relational modellorientiert.

Das Ergebnis von zwei Tabellen JOINed ist ein kartesisches Produkt der Tabellen, auf die ein Filter angewendet wird, der nur die Zeilen mit übereinstimmenden Verbindungsspalten auswählt.

Mit der WHERESyntax ist dies einfacher zu erkennen .

In MySQL (und allgemein in SQL) sind diese beiden Abfragen Synonyme.

Beachten Sie auch, dass MySQL auch eine STRAIGHT_JOINKlausel enthält.

Mit dieser Klausel können Sie die JOINReihenfolge steuern : Welche Tabelle wird in der äußeren Schleife gescannt und welche in der inneren Schleife.

Sie können dies in MySQL nicht mithilfe der WHERESyntax steuern .


10
Danke, Quassnoi. Sie haben viele Details in Ihrer Ans; Ist es fair zu sagen, dass "Ja, diese Abfragen sind gleichwertig, aber Sie sollten Inner Join verwenden, weil es besser lesbar und einfacher zu ändern ist"?
Allyourcode

8
@allyourcode: für Oracle, SQL Server, MySQLund PostgreSQL- ja. Wahrscheinlich auch für andere Systeme, aber Sie sollten dies besser überprüfen.
Quassnoi

13
FWIW, die Verwendung von Kommas mit Verknüpfungsbedingungen in der WHEREKlausel, ist ebenfalls im ANSI-Standard enthalten.
Bill Karwin

1
@Bill Karwin: Das JOINSchlüsselwort war bis in die Vergangenheit nicht Teil proprietärer Standards, wie es scheint. Es hat seinen Weg Oraclenur in in Version 9und in PostgreSQLin Version 7.2(beide veröffentlicht in 2001) gemacht. Das Auftreten dieses Schlüsselworts war Teil der ANSIStandardakzeptanz, und deshalb wird dieses Schlüsselwort normalerweise mit assoziiert ANSI, obwohl letzteres auch Komma als Synonym für unterstützt CROSS JOIN.
Quassnoi

9
Trotzdem hat ANSI SQL-89 angegeben, dass WHEREVerknüpfungen mit Kommas und Bedingungen in einer Klausel ausgeführt werden sollen (ohne Bedingungen entspricht eine Verknüpfung, wie Sie sagten, einer Kreuzverknüpfung). ANSI SQL-92 hat das JOINSchlüsselwort und die zugehörige Syntax hinzugefügt, die Syntax im Kommastil wird jedoch aus Gründen der Abwärtskompatibilität weiterhin unterstützt.
Bill Karwin

182

Andere haben darauf hingewiesen, dass dies INNER JOINdie Lesbarkeit des Menschen verbessert, und das stimmt, da stimme ich zu.
Lassen Sie mich versuchen zu erklären, warum die Join-Syntax besser lesbar ist.

Eine grundlegende SELECTAbfrage lautet wie folgt:

SELECT stuff
FROM tables
WHERE conditions

Die SELECTKlausel sagt uns, was wir zurückbekommen; Die FROMKlausel sagt uns, woher wir es bekommen, und die WHEREKlausel sagt uns, welche wir bekommen.

JOIN ist eine Aussage über die Tabellen, wie sie miteinander verbunden sind (konzeptionell tatsächlich in einer einzigen Tabelle).

Alle Abfrageelemente, die die Tabellen steuern - von denen wir Material beziehen - gehören semantisch zur FROMKlausel (und natürlich JOINgehen dort Elemente hin). Putting Verbindungselemente in die WHEREKlausel verschmilzt die das und das , wo-aus , deshalb die JOINSyntax bevorzugt.


7
Vielen Dank für die Klarstellung, warum Inner Join Carl bevorzugt wird. Ich denke, deine Ans war in den anderen implizit, aber explizit ist normalerweise besser (ja, ich bin ein Python-Fan).
Allyourcode

2
Die Semantik von ON und WHERE bedeutet, dass es für JOINs nach dem letzten OUTER JOIN keine Rolle spielt, welche Sie verwenden. Obwohl Sie ON als Teil von JOIN charakterisieren, handelt es sich auch um eine Filterung nach einem kartesischen Produkt. Sowohl ON als auch WHERE filtern ein kartesisches Produkt. Vor dem letzten OUTER JOIN muss jedoch entweder ON oder eine Unterauswahl mit WHERE verwendet werden . (JOINs sind keine "on" -Spaltenpaare. Zwei beliebige Tabellen können unter jeder Bedingung verbunden werden. Dies ist nur eine Möglichkeit, JOINs ON-Gleichheit von Spalten spezifisch zu interpretieren.)
philipxy

Selbst wenn Sie WHERE mit dem gleichen Effekt wie INNER JOIN verwenden, werden Sie Ihre beiden Tabellen im FROM-Teil der Abfrage erwähnen. Im Grunde genommen implizieren Sie also immer noch, woher Sie Ihre Daten in der FROM-Klausel beziehen. Ich denke, Sie können nicht sagen, dass dies notwendigerweise "das
Was

@ArsenKhachaturyan Nur weil ein Schlüsselwort oder eine Kennung im Text verwendet wird, bedeutet dies nicht, dass es sich um Code handelt und ein Codeformat benötigt. Dies ist eine Formatierungsoption, die in jede Richtung gehen kann. Wenn es sinnvoll ist, hier zu bearbeiten, ist es gerechtfertigt, dass jeder Beitrag ständig im anderen Format bearbeitet wird - das heißt, es ist nicht gerechtfertigt. (Außerdem kann es schwierig sein, das Inline-Codeformat pro Wort zu lesen.) Gleiches gilt für die Absatzumbrüche hier - sie sind nicht besonders klar. Gleiches gilt für 'welches' gegen 'das'. Und Namen von Programmiersprachen sollten nicht im Codeformat vorliegen. PS Sie haben einen fehlerhaften Zeilenumbruch hinzugefügt.
philipxy

@philipxy wie Sie sagten "es bedeutet nicht ...", aber offensichtlich bedeutete das auch nicht, dass es nicht mit einem Code-Schlüsselwort markiert werden kann. Ja, es ist eine Entscheidung zu treffen, aber viele Posts werden gemacht, ohne diese Tatsache zu kennen. Daher soll meine Entscheidung, die Änderungen vorzunehmen, nichts kaputt machen, sondern es lesbarer machen. Wenn Sie nach dem Formatieren von Änderungen eine Unterbrechung bemerkt haben, entschuldigen Sie dies, und Sie können diese Änderungen natürlich rückgängig machen.
Arsen Khachaturyan

143

Anwenden von bedingten Anweisungen in ON / WHERE

Hier habe ich die logischen Abfrageverarbeitungsschritte erklärt.


Referenz: In Microsoft® SQL Server ™ 2005 T-SQL-Abfrage
Herausgeber: Microsoft Press Veröffentlichungsdatum:
07. März 2006
Drucken Sie ISBN-10: 0-7356-2313-9
Drucken Sie ISBN-13: 978-0-7356-2313-2
Seiten: 640

In Microsoft® SQL Server ™ 2005 T-SQL-Abfrage

(8)  SELECT (9) DISTINCT (11) TOP <top_specification> <select_list>
(1)  FROM <left_table>
(3)       <join_type> JOIN <right_table>
(2)       ON <join_condition>
(4)  WHERE <where_condition>
(5)  GROUP BY <group_by_list>
(6)  WITH {CUBE | ROLLUP}
(7)  HAVING <having_condition>
(10) ORDER BY <order_by_list>

Der erste auffällige Aspekt von SQL, der sich von anderen Programmiersprachen unterscheidet, ist die Reihenfolge, in der der Code verarbeitet wird. In den meisten Programmiersprachen wird der Code in der Reihenfolge verarbeitet, in der er geschrieben wurde. In SQL ist die erste Klausel, die verarbeitet wird, die FROM-Klausel, während die SELECT-Klausel, die zuerst angezeigt wird, fast zuletzt verarbeitet wird.

Jeder Schritt generiert eine virtuelle Tabelle, die als Eingabe für den folgenden Schritt verwendet wird. Diese virtuellen Tabellen stehen dem Aufrufer nicht zur Verfügung (Clientanwendung oder äußere Abfrage). Nur die vom letzten Schritt generierte Tabelle wird an den Aufrufer zurückgegeben. Wenn in einer Abfrage keine bestimmte Klausel angegeben ist, wird der entsprechende Schritt einfach übersprungen.

Kurze Beschreibung der Phasen der Verarbeitung logischer Abfragen

Machen Sie sich nicht zu viele Sorgen, wenn die Beschreibung der Schritte vorerst nicht viel Sinn macht. Diese dienen als Referenz. Abschnitte, die nach dem Szenariobeispiel folgen, werden die Schritte ausführlicher behandeln.

  1. FROM: Ein kartesisches Produkt (Cross Join) wird zwischen den ersten beiden Tabellen in der FROM-Klausel ausgeführt, und als Ergebnis wird die virtuelle Tabelle VT1 generiert.

  2. EIN: Der EIN-Filter wird auf VT1 angewendet. Nur Zeilen, für die <join_condition>TRUE ist, werden in VT2 eingefügt.

  3. OUTER (Join): Wenn ein OUTER JOIN angegeben ist (im Gegensatz zu einem CROSS JOIN oder einem INNER JOIN), werden Zeilen aus der oder den erhaltenen Tabellen oder Tabellen, für die keine Übereinstimmung gefunden wurde, als äußere Zeilen zu den Zeilen von VT2 hinzugefügt VT3. Wenn in der FROM-Klausel mehr als zwei Tabellen enthalten sind, werden die Schritte 1 bis 3 zwischen dem Ergebnis des letzten Joins und der nächsten Tabelle in der FROM-Klausel wiederholt angewendet, bis alle Tabellen verarbeitet sind.

  4. WHERE: Der WHERE-Filter wird auf VT3 angewendet. Nur Zeilen, für die <where_condition>TRUE ist, werden in VT4 eingefügt.

  5. GROUP BY: Die Zeilen von VT4 sind basierend auf der in der GROUP BY-Klausel angegebenen Spaltenliste in Gruppen angeordnet. VT5 wird generiert.

  6. WÜRFEL | ROLLUP: Supergruppen (Gruppen von Gruppen) werden zu den Zeilen von VT5 hinzugefügt, wodurch VT6 generiert wird.

  7. HAVING: Der HAVING-Filter wird auf VT6 angewendet. Nur Gruppen, für die <having_condition>TRUE ist, werden in VT7 eingefügt.

  8. SELECT: Die SELECT-Liste wird verarbeitet und generiert VT8.

  9. DISTINCT: Doppelte Zeilen werden aus VT8 entfernt. VT9 wird generiert.

  10. ORDER BY: Die Zeilen von VT9 werden gemäß der in der ORDER BY-Klausel angegebenen Spaltenliste sortiert. Ein Cursor wird erzeugt (VC10).

  11. TOP: Die angegebene Anzahl oder der angegebene Prozentsatz der Zeilen wird ab dem Beginn von VC10 ausgewählt. Tabelle VT11 wird generiert und an den Anrufer zurückgegeben.



Daher filtert (INNER JOIN) ON die Daten (die Datenanzahl von VT wird hier selbst reduziert), bevor die WHERE-Klausel angewendet wird. Die nachfolgenden Verknüpfungsbedingungen werden mit gefilterten Daten ausgeführt, wodurch die Leistung verbessert wird. Danach wendet nur die WHERE-Bedingung Filterbedingungen an.

(Das Anwenden von bedingten Anweisungen in ON / WHERE macht in einigen Fällen keinen großen Unterschied. Dies hängt davon ab, wie viele Tabellen Sie verbunden haben und wie viele Zeilen in jeder Verknüpfungstabelle verfügbar sind.)


10
"Daher filtert (INNER JOIN) ON die Daten (die Datenanzahl von VT wird hier selbst reduziert), bevor die WHERE-Klausel angewendet wird." Nicht unbedingt. Der Artikel handelt von der logischen Reihenfolge der Verarbeitung. Wenn Sie sagen, dass eine bestimmte Implementierung eine Sache vor der anderen tut, sprechen Sie über die implementierte Reihenfolge der Verarbeitung. Implementierungen dürfen beliebige Optimierungen vornehmen, solange das Ergebnis das gleiche ist, als ob die Implementierung der logischen Reihenfolge folgt. Joe Celko hat im Usenet viel darüber geschrieben.
Mike Sherrill 'Cat Recall'

@rafidheen "(INNER JOIN) ON filtert die Daten ... bevor die WHERE-Klausel angewendet wird ... was die Leistung verbessert." Guter Punkt. "Danach gelten nur noch die WHERE-Bedingungen für Filterbedingungen." Was ist mit der HAVING-Klausel?
James

@ James Diese Behauptung von Rafidheen ist falsch. Siehe 'Join-Optimierung' im Handbuch. Auch meine anderen Kommentare auf dieser Seite. (Und MikeSherrill'CatRecall's.) Solche "logischen" Beschreibungen beschreiben den Ergebniswert und nicht, wie er tatsächlich berechnet wird. Es ist nicht garantiert, dass sich ein solches Implementierungsverhalten nicht ändert.
Philipxy

67

Die implizite Join-ANSI-Syntax ist älter, weniger offensichtlich und wird nicht empfohlen.

Darüber hinaus ermöglicht die relationale Algebra die Austauschbarkeit der Prädikate in der WHEREKlausel und der INNER JOIN, sodass selbst bei INNER JOINAbfragen mit WHEREKlauseln die Prädikate vom Optimierer neu angeordnet werden können.

Ich empfehle Ihnen, die Abfragen so gut wie möglich zu schreiben.

Manchmal beinhaltet dies das INNER JOINrelativ "unvollständige" und das Einfügen einiger Kriterien in WHEREdie Liste, um die Liste der Filterkriterien einfacher zu pflegen.

Zum Beispiel anstelle von:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
    AND c.State = 'NY'
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
    AND a.Status = 1

Schreiben:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
WHERE c.State = 'NY'
    AND a.Status = 1

Aber es kommt natürlich darauf an.


16
Dein erster Ausschnitt tut meinem Gehirn definitiv mehr weh. Macht das eigentlich jemand? Wenn ich jemanden treffe, der das tut, ist es für mich in Ordnung, ihn über den Kopf zu schlagen?
Allyourcode

3
Ich finde die Kriterien dort, wo es am sinnvollsten ist. Wenn ich mich einer zeitlich konsistenten Snapshot-Nachschlagetabelle anschließe (und keine Ansicht oder UDF habe, die die Auswahl eines gültigen Datums erzwingt), werde ich das Datum des Inkrafttretens in den Join und nicht in das WHERE aufnehmen, da es weniger ist wahrscheinlich versehentlich entfernt werden.
Cade Roux

14
@allyourcode: Obwohl diese Art der Join-Syntax in INNER JOINs selten vorkommt, ist sie bei RIGHT JOINs und LEFT JOINS häufig anzutreffen. Wenn Sie mehr Details im Join-Prädikat angeben, ist keine Unterabfrage erforderlich, und es wird verhindert, dass Ihre äußeren Joins versehentlich gedreht werden in INNER JOINs. (Obwohl ich damit einverstanden bin, dass ich für INNER JOINs fast immer c.State = 'NY' in die WHERE-Klausel eingefügt habe)
Dave Markle

1
@allyourcode Das mache ich definitiv! Und ich stimme Cade zu. Ich bin gespannt, ob es einen vernünftigen Grund gibt, dies nicht zu
tun

31

Implizite Verknüpfungen (wie Ihre erste Abfrage genannt wird) werden viel verwirrender, schwer lesbar und schwer zu pflegen, sobald Sie Ihrer Abfrage weitere Tabellen hinzufügen müssen. Stellen Sie sich vor, Sie führen dieselbe Abfrage und denselben Join-Typ für vier oder fünf verschiedene Tabellen durch ... es ist ein Albtraum.

Die Verwendung eines expliziten Joins (Ihr zweites Beispiel) ist viel besser lesbar und einfach zu warten.


48
Ich konnte nicht mehr widersprechen. Die JOIN-Syntax ist extrem wortreich und schwer zu organisieren. Ich habe viele Abfragen, die 5, 10 oder sogar 15 Tabellen mit WHERE-Klausel-Joins verbinden, und sie sind perfekt lesbar. Das Umschreiben einer solchen Abfrage mithilfe einer JOIN-Syntax führt zu einem verstümmelten Durcheinander. Was nur zeigt, dass es keine richtige Antwort auf diese Frage gibt und dass es mehr darauf ankommt, womit Sie sich wohl fühlen.
Noah Yetter

33
Noah, ich denke du bist hier in der Minderheit.
Matt B

2
Ich bekomme +1 für Matt und Noah. Ich mag Vielfalt :). Ich kann sehen, woher Noah kommt; Inner Join fügt der Sprache nichts Neues hinzu und ist definitiv ausführlicher. Auf der anderen Seite kann dies Ihren "Wo" -Zustand viel kürzer machen, was normalerweise bedeutet, dass es leichter zu lesen ist.
Allyourcode

5
Ich würde davon ausgehen, dass jedes vernünftige DBMS die beiden Abfragen in denselben Ausführungsplan übersetzt. In Wirklichkeit ist jedoch jedes DBMS anders und die einzige Möglichkeit, dies sicher zu wissen, besteht darin, den Ausführungsplan tatsächlich zu überprüfen (dh Sie müssen ihn selbst testen).
Matt B

Stimmt es, wie @rafidheen in einer anderen Antwort (der mit der detaillierten Reihenfolge der SQL-Ausführung) vorgeschlagen hat, dass JOINs einzeln gefiltert werden, wodurch die Größe der Verknüpfungsoperationen im Vergleich zu einer vollständigen kartesischen Verknüpfung von 3 oder mehr Tabellen mit verringert wird? Wird der WHERE-Filter rückwirkend angewendet? In diesem Fall würde JOIN eine Leistungsverbesserung bieten (sowie Vorteile bei Links / Rechts-Verknüpfungen, wie auch in einer anderen Antwort erwähnt).
James

26

Ich werde auch darauf hinweisen, dass die Verwendung der älteren Syntax eher fehleranfällig ist. Wenn Sie innere Verknüpfungen ohne ON-Klausel verwenden, wird ein Syntaxfehler angezeigt. Wenn Sie die ältere Syntax verwenden und eine der Join-Bedingungen in der where-Klausel vergessen, erhalten Sie einen Cross-Join. Die Entwickler beheben dies häufig, indem sie das eindeutige Schlüsselwort hinzufügen (anstatt den Join zu reparieren, da sie immer noch nicht erkennen, dass der Join selbst beschädigt ist). Dies scheint das Problem zu beheben, verlangsamt jedoch die Abfrage erheblich.

Woher weiß der Betreuer bei Wartungsarbeiten, wenn Sie einen Cross-Join in der alten Syntax haben, ob Sie einen haben wollten (es gibt Situationen, in denen Cross-Joins erforderlich sind) oder ob es sich um einen Unfall handelte, der behoben werden sollte?

Lassen Sie mich auf diese Frage hinweisen, um zu sehen, warum die implizite Syntax schlecht ist, wenn Sie linke Verknüpfungen verwenden. Sybase * = nach Ansi Standard mit 2 verschiedenen äußeren Tabellen für dieselbe innere Tabelle

Außerdem ist der Standard, der die expliziten Verknüpfungen verwendet, über 20 Jahre alt, was bedeutet, dass die implizite Verknüpfungssyntax für diese 20 Jahre veraltet ist. Würden Sie Anwendungscode mit einer Syntax schreiben, die seit 20 Jahren veraltet ist? Warum möchten Sie also Datenbankcode schreiben?


3
@HLGEM: Obwohl ich völlig damit einverstanden bin, dass explizite JOINs besser sind, gibt es Fälle, in denen Sie nur die alte Syntax verwenden müssen. Ein Beispiel aus der Praxis: ANSI JOIN ist erst in Version 9i in Oracle eingestiegen, die 2001 veröffentlicht wurde, und bis vor einem Jahr (16 Jahre nach Veröffentlichung des Standards) musste ich eine Reihe von 8i-Installationen unterstützen, für die wir eine hatten um kritische Updates freizugeben. Ich wollte nicht zwei Sätze von Updates verwalten, deshalb haben wir die Updates für alle Datenbanken einschließlich 8i entwickelt und getestet, was bedeutete, dass wir keine ANSI JOINs verwenden konnten.
Quassnoi

+1 interessanter Punkt, wenn Sie darauf hinweisen, dass die Sintax ohne INNER JOIN fehleranfälliger ist. Ich bin verwirrt über Ihren letzten Satz, wenn Sie sagen "... der Standard, der die expliziten Verknüpfungen verwendet, ist 17 Jahre alt." Schlagen Sie dann vor, das Schlüsselwort INNER JOIN zu verwenden, oder nicht?
Marco Demaio

1
@Marco Demaio, ja, verwenden Sie immer INNER JOIN oder JOIN (diese beiden sind gleich) oder LEFT JOIN oder RIGHT JOIN oder CROSS JOIN und verwenden Sie niemals die impliziten Komma-Joins.
HLGEM

2
"Warum möchten Sie Datenbankcode schreiben, der [20 Jahre alt] ist?" - Ich stelle fest, dass Sie SQL schreiben, HAVINGdas veraltet ist, seit SQL abgeleitete Tabellen unterstützt. Ich stelle auch fest, dass Sie nicht verwenden NATURAL JOIN, obwohl ich behaupten würde, dass es INNER JOIN"veraltet" ist. Ja, Sie haben Ihre Gründe (Sie müssen sie hier nicht noch einmal angeben!): Mein Punkt ist, dass diejenigen, die gerne die ältere Syntax verwenden, auch ihre Gründe haben und das relative Alter der Syntax von geringer oder gar keiner Relevanz ist.
Tag, wenn

1
WO ist noch im Standard (zeig mir wo es nicht ist). Also anscheinend nichts veraltetes. Auch „anstatt Festsetzung der Join“ zeigt mir einen Entwickler, der in der Regel von DBMS - Systemen entfernt gehalten werden soll , weit weg.
Jürgen A. Erhard

12

Sie haben eine andere vom Menschen lesbare Bedeutung.

Abhängig vom Abfrageoptimierer haben sie jedoch möglicherweise dieselbe Bedeutung für den Computer.

Sie sollten immer Code verwenden, um lesbar zu sein.

Das heißt, wenn dies eine integrierte Beziehung ist, verwenden Sie den expliziten Join. Wenn Sie mit schwach verwandten Daten übereinstimmen, verwenden Sie die where-Klausel.


11

Der SQL: 2003-Standard hat einige Vorrangregeln geändert, sodass eine JOIN-Anweisung Vorrang vor einem "Komma" -Verbindung hat. Dies kann die Ergebnisse Ihrer Abfrage abhängig von der Einrichtung tatsächlich ändern. Dies verursacht für einige Leute einige Probleme, als MySQL 5.0.12 auf die Einhaltung des Standards umstellte.

In Ihrem Beispiel würden Ihre Abfragen also genauso funktionieren. Wenn Sie jedoch eine dritte Tabelle hinzugefügt haben: SELECT ... FROM table1, table2 JOIN table3 ON ... WHERE ...

Vor MySQL 5.0.12 wurden zuerst Tabelle1 und Tabelle2 und dann Tabelle3 verbunden. Jetzt (5.0.12 und höher) werden zuerst Tabelle2 und Tabelle3 verbunden, dann Tabelle1. Es ändert nicht immer die Ergebnisse, aber es kann und Sie können es nicht einmal realisieren.

Ich verwende nie mehr die "Komma" -Syntax und entscheide mich für Ihr zweites Beispiel. Es ist sowieso viel besser lesbar, die JOIN-Bedingungen gelten für die JOINs und sind nicht in einen separaten Abfrageabschnitt unterteilt.


Standard SQL hat sich nicht geändert. MySQL war einfach falsch und jetzt ist es richtig. Siehe das MySQL-Handbuch.
philipxy

4

Ich weiß, dass Sie über MySQL sprechen, aber trotzdem: In Oracle 9 würden explizite und implizite Verknüpfungen unterschiedliche Ausführungspläne generieren. AFAIK, das in Oracle 10+ gelöst wurde: Es gibt keinen solchen Unterschied mehr.


1

Die ANSI-Join-Syntax ist definitiv portabler.

Ich mache ein Upgrade von Microsoft SQL Server durch und möchte auch erwähnen, dass die Syntax = * und * = für äußere Verknüpfungen in SQL Server für 2005 SQL Server und höher nicht unterstützt wird (ohne Kompatibilitätsmodus).


2
Selbst in SQL Server 2000 können = und = zu falschen Ergebnissen führen und sollten niemals verwendet werden.
HLGEM

2
*=und =*waren nie ANSI und waren nie eine gute Notation. Aus diesem Grund wurde ON benötigt - für OUTER JOINs ohne Unterauswahl (die gleichzeitig hinzugefügt wurden, sodass sie in CROSS & INNER JOINs nicht benötigt werden.)
philipxy

1

Wenn Sie häufig dynamische gespeicherte Prozeduren programmieren, werden Sie sich in Ihr zweites Beispiel verlieben (mit where). Wenn Sie verschiedene Eingabeparameter und viel Morph-Chaos haben, ist dies der einzige Weg. Andernfalls führen beide denselben Abfrageplan aus, sodass bei klassischen Abfragen definitiv kein offensichtlicher Unterschied besteht.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.