Gibt es einen wesentlichen Unterschied zwischen Abfragen, die durch WHERE-Klauseln verknüpft sind, und Abfragen, die einen tatsächlichen JOIN verwenden?

32

In Learn SQL the Hard Way (Übung 6) präsentiert der Autor die folgende Abfrage:

SELECT pet.id, pet.name, pet.age, pet.dead
    FROM pet, person_pet, person
    WHERE
    pet.id = person_pet.pet_id AND
    person_pet.person_id = person.id AND
    person.first_name = "Zed";

und sagt dann weiter:

Es gibt tatsächlich andere Möglichkeiten, diese Art von Abfragen zum Funktionieren zu bringen, die als "Verknüpfungen" bezeichnet werden. Ich vermeide diese Konzepte vorerst, weil sie wahnsinnig verwirrend sind. Halten Sie sich fürs Erste an diese Art des Zusammenfügens von Tabellen und ignorieren Sie Leute, die versuchen, [Ihnen] zu sagen, dass dies irgendwie langsamer oder "niedriger" ist.

Ist das wahr? Warum oder warum nicht?

Robert Harvey
quelle
3
Ich glaube nicht, dass dies der Fall ist, aber Sie könnten versuchen, EXPLAIN auszuführen, um festzustellen, ob es Unterschiede bei der Ausführung der Abfrage gibt.
GroßmeisterB
6
Ich möchte die widersprüchlichen Signale einer Arbeit mit "the Hard Way" im Titel hervorheben und ein Konzept überspringen, "weil sie wahnsinnig verwirrend sind". Aber vielleicht ist nur mein Konzept, was "der harte Weg" sein sollte, falsch. Aber vielleicht auch nicht.
Mindwin
7
JOIN transportiert sehr gut die Absicht (Tabellen verbinden), so dass der WHERE-Teil für die eigentlichen Filter übrig bleibt und es nur ein bisschen leichter zu lesen ist. (Neben vielen anderen Implikationen)
Do.,
2
Sie lernen SQL auf die harte Tour, wenn der Autor nicht die Mühe hat, einfache Joins zu schreiben! Wie ThomasS durch die Verwendung von JOINs sagt, werden die Absichten klarer und die WHERE-Klauseln werden viel einfacher. Auch die Verwendung von JOINs veranschaulicht die Mengenlehre besser, die SQL untermauert.
Daniel Hollinrake
1
Ich bin mir nicht sicher, wie ich mich bei etwas fühle, das Ihnen etwas beibringen soll, während ich sage: "Aber hey, wir werden dieses grundlegende Konzept überspringen, weil es sich um verrückte Bananen handelt." Ich denke, ich würde am Ende nach einer anderen Quelle suchen, aus der ich lernen kann. Irgendwann müssen Sie Outer-Joins und Cross-Joins ausführen und sollten wissen, wie diese ausgeführt werden.
Maurice Reeves

Antworten:

23

Mit dem Ansatz des Autors wird das Unterrichten von OUTER JOINs sehr viel schwieriger. Die ON-Klausel in INNER JOIN hat mich nie umgehauen wie viele andere Sachen. Vielleicht liegt es daran, dass ich nie den alten Weg gelernt habe. Ich würde gerne glauben, dass es einen Grund dafür gibt, warum wir es losgeworden sind, und es war nicht so einfach, diese Methode als low class zu bezeichnen.

Es ist wahr, in dem sehr engen Szenario, das der Autor erstellt hat:

  • Ein solcher SQL-Einstieg mit ON ist komplex
  • Berücksichtigt nur JOIN / INNER JOIN und keine OUTER JOINs
  • Der isolierte Codierer, der weder den Code eines anderen lesen muss noch Personen mit Erfahrung in der Verwendung von ON hat, die ihren Code lesen / verwenden.
  • Keine komplexe Abfrage mit vielen: Tabellen, wenn, aber und oder.

Als Teil eines Lehrfortschritts denke ich, dass es einfacher ist, ihn zu zerlegen und einen natürlichen Fortschritt zu haben:

Select * from table
select this, something, that from table
select this from table where that = 'this'
select this from table join anothertable on this.id = that.thisid

Die Konzepte zum Verknüpfen und Filtern von Tabellen sind nicht wirklich identisch. Die korrekte Syntax Lernen wird nun carry-over haben , wenn Sie OUTER lernen JOINS es sei denn , der Autor auf die Lehre veraltet / veraltet Dinge will wie: *= or =*.

JeffO
quelle
5
Der Grund, warum die JOIN-Anweisung hinzugefügt wurde, war, dass es keinen Standard für das Ausdrücken von Outer-Joins gab, sodass jeder Datenbankanbieter seine eigene (inkompatible) "spezielle" Syntax dafür hatte. IIRC Oracle hatte *=oder =*zeigte linke oder rechte äußere Verknüpfungen an, eine andere, die ich nur mit einem |=Operator unterstützte.
TMN
1
@TMN IIRC Oracle verwendet +=oder vielleicht war es =+. Ich glaube, *=war Transact-SQL (Sybase und später MS-SQL). Trotzdem guter Punkt.
David
1
Wenn Sie eine Mischung aus inneren und äußeren Verknüpfungen haben, wird es kompliziert (IMHO). In solchen Situationen werde ich zugeben, dass ich manchmal auf die "einfache" Technik zurückgreife, meine Verknüpfungen in der WHEREKlausel auszuführen. (Ich habe gehört, dass dies als Theta-Join bezeichnet wird, bin mir aber nicht sicher, ob das richtig ist.)
David,
IIRC-Operatoren wie "größer als" oder "gleich" wurden manchmal als "Theta-Operatoren" bezeichnet, aber eine Google-Suche führt zu einigen Operationen in der Analysis.
Walter Mitty
12

Ob es langsamer ist, hängt vom Abfrageoptimierer ab und davon, wie es die Abfrage optimiert (was Sie schreiben, ist nicht das, was ausgeführt wird). Das große Problem bei diesem Zitat ist jedoch, dass die Tatsache, dass es verschiedene Arten von Joins gibt, die völlig unterschiedlich funktionieren, völlig ignoriert wird. Zum Beispiel ist das Gesagte (theoretisch) wahr inner joins, aber es gilt nicht für outer joins( left joinsund right joins).

Locke
quelle
9
+1 Für andere Arten von Joins. Die meisten meiner Joins sind entweder INNER JOINoder LEFT OUTER JOIN. Sie sind nicht "wahnsinnig verwirrend". SQL kann wahnsinnig verwirrend werden, aber dies ist kein Beispiel dafür.
mgw854
off topic , aber soll die Aussage verschiedene Typen beitreten s oder Join - Typen von ?
user1451111
9

Der Autor stellt einen einfachen Fall vor, in dem entweder die alte oder die neue Syntax verwendet werden kann. Ich stimme seiner Aussage nicht zu, dass Verknüpfungen wahnsinnig verwirrend sind, da das Verknüpfen von Tabellen ein grundlegendes SQL-Abfragekonzept ist. Vielleicht sollte der Autor vorher einige Zeit damit verbracht haben, die Funktionsweise von JOINS zu erläutern, bevor er eine Stellungnahme abgibt und ein Beispiel für eine Abfrage mehrerer Tabellen ausführt.

Man sollte die neuere Syntax verwenden. Das Hauptargument dafür ist, dass Ihre Abfrage Folgendes haben wird:

  • Wählen Sie Kriterien
  • Beitrittskriterien
  • Filterkriterien

Bei Verwendung des alten Stils werden die Join- und Filterkriterien kombiniert, was in komplexeren Fällen zu Verwirrung führen kann.

Sie können ein kartesisches Produkt auch erhalten, indem Sie ein Verknüpfungskriterium in der Filterklausel vergessen:

 person_pet.person_id = person.id

mit der älteren Syntax.

Die Verwendung der neueren Syntax gibt auch an, wie der Join erfolgen soll. Dies ist wichtig, wenn Sie ein INNER, LEFT OUTER usw. verwenden möchten. In Bezug auf die JOIN-Syntax ist es daher eindeutiger, dass IMHO die Lesbarkeit für diejenigen erhöht, die mit dem Verknüpfen von Tabellen nicht vertraut sind.

Jon Raynor
quelle
5

Es sollte keine geben, der Abfrageparser sollte eine äquivalente interne Darstellung für äquivalente Abfragen generieren, unabhängig davon, wie sie geschrieben wurden. Der Autor verwendet nur die Pre-SQL-92-Syntax, weshalb er erwähnt, dass sie möglicherweise als "altmodisch" oder "niedrig" eingestuft wird. Intern sollten der Parser und der Optimierer denselben Abfrageplan generieren.

TMN
quelle
5

Auf diese Weise habe ich SQL gelernt, einschließlich der *=Syntax für äußere Verknüpfungen. Für mich war es sehr intuitiv, da alle Beziehungen den gleichen Vorrang hatten und Abfragen besser als eine Reihe von Fragen aufstellten: Was möchten Sie? Woher willst du sie? Welche möchtest du?

Durch die joinSyntax wird der Denkprozess gegenüber den Beziehungen stärker gestört. Und persönlich finde ich den Code weitaus weniger lesbar, da die Tabellen und Beziehungen vermischt sind.

Zumindest in MSSQL gibt es keinen signifikanten Unterschied in der Leistung der Abfragen, vorausgesetzt, Sie verwenden dieselbe Verknüpfungsreihenfolge. Das heißt, es gibt ein klares, großes Problem beim Erlernen (und Verwenden) von SQL auf diese Weise. Wenn Sie eine Ihrer Beziehungen vergessen, erhalten Sie unerwartete Cross-Produkte. Was in einer Datenbank von beliebiger Größe unerschwinglich teuer ist (und für Nichtauserwählte gefährlich ist!). Es ist viel schwieriger, eine Beziehung zu vergessen, wenn Sie die joinStilsyntax verwenden.

Telastyn
quelle
7
Da es sich um eine relationale Datenbank handelt, sind die Beziehungen für eine Abfrage ziemlich wichtig. Ich persönlich finde es viel schwieriger, eine Abfrage zu verstehen, bei der echte Filter (foo.x = 5) mit Beziehungen (foo.x = bar.x) gemischt werden. Die Engine kann dies leicht in einen Join optimieren, aber ein Mensch muss im Wesentlichen zeilenweise darüber nachdenken, im Gegensatz zu Mengen und Teilmengen.
Aaronaught
4

Hierbei sind zwei verschiedene Aspekte zu berücksichtigen: Leistung und Wartbarkeit / Lesbarkeit .

Wartbarkeit / Lesbarkeit

Ich habe eine andere Abfrage ausgewählt, da dies meines Erachtens ein besseres / schlechteres Beispiel ist als die ursprüngliche Abfrage, die Sie veröffentlicht haben.

Was sieht für Sie besser aus und ist besser lesbar?

select
    e.LoginID,
    DepartmentName = d.Name
from HumanResources.Employee e
inner join HumanResources.EmployeeDepartmentHistory edh
on e.BusinessEntityID = edh.BusinessEntityID
inner join HumanResources.Department d
on edh.DepartmentID = d.DepartmentID
where d.Name = 'Engineering';

Oder...

select
    e.LoginID,
    DepartmentName = d.Name
from HumanResources.Employee e, 
HumanResources.EmployeeDepartmentHistory edh,
HumanResources.Department d
where e.BusinessEntityID = edh.BusinessEntityID
and edh.DepartmentID = d.DepartmentID
and d.Name = 'Engineering';

Für mich persönlich ist der erste sehr gut lesbar. Sie sehen, dass wir Tabellen mit verknüpfen INNER JOIN, was bedeutet, dass wir die Zeilen abrufen, die mit der nachfolgenden Verknüpfungsklausel übereinstimmen (dh "Mitarbeiter mit EmployeeDepartmentHistory auf BusinessEntityID verknüpfen und diese Zeilen einschließen").

Letzteres bedeutet mir das Komma nichts. Ich frage mich, was Sie mit all diesen WHEREKlauselprädikaten machen.

Ersteres liest sich eher so, wie mein Gehirn denkt. Ich sehe mir jeden Tag den ganzen Tag SQL an und die Kommas für Joins. Was mich zu meinem nächsten Punkt führt ...

Es gibt tatsächlich andere Möglichkeiten, diese Art von Abfragen zum Funktionieren zu bringen, die als "Verknüpfungen" bezeichnet werden.

Sie sind alle miteinander verbunden. Sogar das Komma ist ein Join. Die Tatsache, dass der Autor sie nicht nennt, ist in der Tat ihr Untergang ... es ist nicht offensichtlich. Es sollte offensichtlich sein. Sie verbinden relationale Daten, unabhängig davon, ob Sie dies angebenJOIN oder ,.

Performance

Dies wird definitiv RDBMS-abhängig sein. Ich kann nur im Auftrag von Microsoft SQL Server sprechen. In Bezug auf die Leistung sind diese gleichwertig. Woher weißt du das? Erfassen Sie die Post-Execution-Pläne und sehen Sie, was genau SQL Server für jede dieser Anweisungen tut:

Bildbeschreibung hier eingeben

Im obigen Bild habe ich hervorgehoben, dass ich beide Abfragen wie oben verwende und mich nur in den expliziten Zeichen für den Join unterscheide (JOIN vs ,) unterscheide. SQL Server macht genau dasselbe.

Zusammenfassung

Verwenden Sie keine Kommas. Verwenden Sie explizite JOINAnweisungen.

Thomas Stringer
quelle
Ich habe INNER JOINs gelernt, lange bevor mir klar wurde, dass die Variante mit den WHERE-Klauseln äquivalent ist und beide Beispiele für mich sehr lesbar sind. Das mit den WHEREs und den Kommas ist möglicherweise noch besser lesbar. Wo es runterfällt, denke ich, sind große komplexe Abfragen, nicht diese relativ einfachen.
Robert Harvey
Der Punkt ist, zu denken, dass die Kommavariation keine relationale Verknüpfung ist, ist überhaupt nicht korrekt.
Thomas Stringer
Ich denke, Sie interpretieren die Kommas falsch als Verknüpfungen. Die Kommas trennen nur Tabellen; Es sind die WHERE-Bedingungen, die die Joins erzeugen, nicht die Kommas.
Robert Harvey
1
Ich kann mit Bestimmtheit sagen, dass in den Prädikatssätzen keinerlei Beitritt stattfindet. Ich denke, Sie interpretieren die Konstrukte Ihrer relationalen Abfrage falsch. Haben Sie versucht, Ihr Komma ohne die WHERE-Klauseln zu verbinden? Es funktioniert noch. Es ist eine kartesische Verbindung. Was gewinnen Sie durch die Verwendung von Kommas? Bitte sagen Sie nicht, dass Sie versuchen, Zeichen zu speichern.
Thomas Stringer
1
Ich würde sagen, der erste ist besser, weil Ihre Absichten klarer sind. Es gibt viel weniger Mehrdeutigkeiten.
Daniel Hollinrake
4

Nein, das stimmt überhaupt nicht. Der Autor bereitet seine Leser auf Verwirrung vor und ermutigt zur Cargo-Kult-Programmierung, die einen sehr starken strukturellen Unterschied zwischen der Standardsyntax und dieser älteren Variante, die er bevorzugt, vermeidet. Insbesondere macht es eine überfüllte WHERE-Klausel schwieriger, herauszufinden, was seine Abfrage besonders macht.

Sein Beispiel veranlasst einen Leser, eine mentale Karte seiner Bedeutung zu generieren, die eine Menge Unordnung aufweist.

SELECT pet.id, pet.name, pet.age, pet.dead
    FROM pet, person_pet, person
    WHERE
    pet.id = person_pet.pet_id AND
    person_pet.person_id = person.id AND
    person.first_name = "Zed";

Grob gesagt ist das obige:

Rufen Sie die ID, den NAMEN, das ALTER und den TOTEN des Haustiers für alle Haustiere, person_pet und Personen ab, bei denen die Haustier-ID mit der pet_id eines person_pet übereinstimmt und die person_id dieses Datensatzes mit der person_id einer Person übereinstimmt, deren FIRST_NAME "Zed" ist.

Mit einer solchen mentalen Karte kann der Leser (der aus irgendeinem Grund die SQL von Hand schreibt) sehr leicht einen Fehler machen, möglicherweise indem er eine oder mehrere Tabellen weglässt. Und ein Leser von Code, der so geschrieben ist, muss härter arbeiten, um genau herauszufinden, was der SQL-Autor versucht. ("Harder" ist auf der Ebene des Lesens von SQL mit oder ohne Syntaxhervorhebung, aber es ist immer noch ein Unterschied von mehr als Null.)

Es gibt einen Grund, warum JOINs üblich sind, und es ist der alte Klassiker unter den Canards, bei denen es um die Trennung von Interessen geht. Insbesondere für eine SQL-Abfrage gibt es einen guten Grund, die Struktur der Daten von der Filterung der Daten zu unterscheiden.

Wenn die Abfrage sauberer geschrieben ist, wie z

SELECT pet.id, pet.name, pet.age
FROM pet
  JOIN person_pet ON pet.id = person_pet.pet_id
  JOIN person ON person.id = person_pet.person_id
WHERE 
  person.first_name = "Zed";

Dann hat der Leser eine klarere Unterscheidung zwischen den Komponenten dessen, was gefragt wird. Der Unterscheidungsfilter dieser Abfrage ist von der Beziehung seiner Komponenten zueinander getrennt, und die erforderlichen Komponenten jeder Beziehung befinden sich direkt neben dem Ort, an dem sie benötigt werden.


Natürlich sollte ein modernes Datenbanksystem keinen signifikanten Unterschied zwischen den beiden Stilen erkennen. Wenn jedoch die Datenbankleistung die einzige Überlegung wäre, würde die SQL-Abfrage auch keinen Leerraum oder keine Großschreibung aufweisen.

DougM
quelle
2
Da ich diesen Refrain jetzt schon mehrmals gehört habe, lass mich Devil's Advocate spielen. Bei Learn X the Hard Way geht es um technische Tiefe. Jeder mit einem guten Verständnis von SQL sollte wirklich wissen, dass die beiden Ansätze in Bezug auf die Ausgabe, die sie produzieren, gleichwertig sind .
Robert Harvey
1
Ich kann das sehen, aber der Autor behauptet nicht einfach, dass es sich um äquivalente Aussagen zu einem anständigen SQL-Server handelt. Sie behaupten, dass die Verwendung von JOIN "verwirrend" ist. Dies ist ein Pfad, auf dem schmutziger Code wartet. ("Nein, verwenden Sie LINQ nicht, schreiben Sie einfach Ihre FOR-Anweisung von Hand." "Dem Compiler ist es egal, wie ich diese Methode nenne, daher gibt es keinen Grund, sie nicht FN1 zu nennen.")
DougM
3

Guy macht einen klassischen Fehler. Er versucht, ein abstraktes Konzept mit einer bestimmten Implementierung zu vermitteln. Sobald Sie das tun, geraten Sie in dieses Chaos.

Sollte zuerst grundlegende Datenbankkonzepte vermittelt haben, dann sollte SQL als eine Möglichkeit zur Beschreibung dieser Konzepte gezeigt werden.

Links und rechts verbinden sich, man könnte behaupten, dass sie nicht allzu wichtig sind. Outer Join, nun, Sie könnten die alte *=und =*Syntax verwenden.

Nun könnte man argumentieren, dass die Syntax einfacher ist, aber nur für einfache Abfragen. Sobald Sie versuchen, mit dieser Version eine komplexe Abfrage durchzuführen, können Sie in ein schreckliches Chaos geraten. Die "neue" Syntax wurde nicht eingeführt, damit Sie komplexe Abfragen ausführen können. Sie haben komplexe Abfragen auf lesbare und daher wartbare Weise ausgeführt.

Tony Hopkinson
quelle
3
"Learn X the Hard Way" ist ein anderer Lernansatz. Sie schreiben den Code und verstehen ihn später.
Robert Harvey
7
@RobertHarvey Das ist kein anderer Lernansatz, es ist der Standard. Später passiert das nur, wenn Sie beim Abspringen der Räder noch an Ort und Stelle sind. Es wurde viel zu viel mit SQL-Schreibern zu tun gehabt, die eine Tabelle für ein rechteckiges Array von Zellen hielten, um Vertrauen in diese Methode zu haben.
Tony Hopkinson
2

Das Beispiel entspricht der einfachen Neuformulierung mit inneren JOINs. Der Unterschied liegt allein in den zusätzlichen Möglichkeiten, die die JOIN-Syntax bietet. Sie können beispielsweise die Reihenfolge angeben, in der die Spalten der beiden beteiligten Tabellen verarbeitet werden. Siehe z . B. https://stackoverflow.com/a/1018825/259310 .

Die empfangene Weisheit besteht darin, Ihre Anfragen im Zweifelsfall so zu schreiben, dass sie besser lesbar sind. Ob JOIN- oder WHERE-Formulierungen jedoch leichter zu lesen sind, scheint eine Frage der persönlichen Präferenz zu sein, weshalb beide Formen so verbreitet sind.

Kilian Foth
quelle
Gute Antwort. Ob Sie WHEREdie Klausel verwenden oder in die JOINAnweisung einfügen, kann sich je nach Abfrageoptimierung tatsächlich auf die Leistung auswirken. Ich habe es mehr als einmal gesehen.
Locke
Meine Erfahrung mit den Auswirkungen auf die Leistung ist folgende: Durch implizite Verknüpfungen stehen dem Abfrageoptimierer mehr Optionen zur Optimierung der Abfrage zur Verfügung. Dies scheint eine gute Sache zu sein, kann jedoch ein Problem darstellen. Insbesondere kann das Abfrageoptimierungsprogramm die Abfrage in der Entwicklung auf die eine und in der Produktion auf die andere Weise optimieren. Das Optimierungsprogramm kann zu einer Optimierung verleitet werden, die die Leistung verringert. Meine Empfehlung lautet, explizite Join-Syntax zu verwenden UND zu bestätigen, dass der Join Spalten mit Indizes verwendet, damit die Leistung vorhersehbar ist.
Michael Potter
2

Als ich SQL lernte, existierten die Formulare INNER JOIN, LEFT JOIN usw. nicht. Wie bereits in anderen Antworten erwähnt, wurden in verschiedenen SQL-Dialekten jeweils Outer-Joins mit eigenwilliger Syntax implementiert. Diese beschädigte Portabilität von SQL-Code. Das Zusammenführen der Sprache erforderte einige Änderungen, und LEFT JOIN usw. war das, worauf sie sich einließen.

Es ist wahr, dass für jeden INNER JOIN ein gleichwertiger Komma-Join mit der Join-Bedingung in der WHERE-Klausel geschrieben werden kann. Ich habe eine Weile gebraucht, um von der Vorliebe für die alte Form zur Vorliebe für die neue Form überzugehen. Offenbar hält der Autor von Learning SQL the Hard Way den alten Weg immer noch für einfacher.

Gibt es da unterschiede Na ja, das gibt es. Das erste ist, dass ein INNER JOIN mit einer ON-Klausel die Absicht des Autors klarer offenbart als der Join im alten Stil. Die Tatsache, dass die ON-Klausel tatsächlich eine Join-Bedingung und keine andere Einschränkung ist, ist offensichtlicher. Dadurch ist Code, der INNER JOIN verwendet, beim Lesen leichter zu erlernen als der alte Stil. Dies ist wichtig, wenn Sie den Code eines anderen Benutzers verwalten.

Der zweite Unterschied besteht darin, dass der neue Stil es dem Abfrageoptimierer geringfügig erleichtert, die Gewinnstrategie zu ermitteln. Dies ist ein sehr kleiner Effekt, aber er ist real.

Der dritte Unterschied besteht darin, dass beim Lernen mit INNER JOIN (oder einfach nur JOIN) das Erlernen von LEFT JOIN usw. erleichtert wird.

Abgesehen davon gibt es überhaupt keinen materiellen Unterschied.

Walter Mitty
quelle
0

Es kommt darauf an, ob Sie in Mengen und formaler Logik denken.

Wenn Sie das Schlüsselwort "join" nicht verwenden, wird der Übergang von der formalen Logik zu SQL vereinfacht.

Aber wenn Sie, wie 99% der Menschen, in Ihrem Mathematikstudium keinen Spaß an formaler Logik hatten, ist das Join-Schlüsselwort ein einfacherer Lerneffekt. Früher wurde SQL an der Universität präsentiert, um formale logische Abfragen niederzuschreiben.

Ian
quelle