281 Stimmen

Bedingung in JOIN oder WHERE

Gibt es einen Unterschied (Leistung, Best-Practice usw.) zwischen dem Einfügen einer Bedingung in die JOIN-Klausel und der WHERE-Klausel?

Zum Beispiel...

-- Condition in JOIN
SELECT *
FROM dbo.Customers AS CUS
INNER JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
AND CUS.FirstName = 'John'

-- Condition in WHERE
SELECT *
FROM dbo.Customers AS CUS
INNER JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
WHERE CUS.FirstName = 'John'

Welche bevorzugen Sie (und warum?)?

205voto

Cade Roux Punkte 85601

Die relationale Algebra ermöglicht die Austauschbarkeit der Prädikate in der WHERE Klausel und die INNER JOIN also auch INNER JOIN Abfragen mit WHERE Klauseln können die Prädikate durch den Optimierer neu angeordnet werden, so dass sie kann bereits ausgeschlossen sein während der JOIN Prozess.

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

Dazu gehört manchmal auch, dass die INNER JOIN relativ "unvollständig" zu sein und einige der Kriterien in die WHERE um die Listen der Filterkriterien leichter pflegen zu können.

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.

183voto

HLGEM Punkte 91543

Bei inneren Joins habe ich keinen wirklichen Unterschied festgestellt (aber wie bei jeder Leistungsoptimierung müssen Sie Ihre Datenbank unter Ihren Bedingungen überprüfen).

Allerdings macht es einen großen Unterschied, wo Sie die Bedingung setzen, wenn Sie linke oder rechte Verbindungen verwenden. Betrachten Sie zum Beispiel diese beiden Abfragen:

SELECT *
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
WHERE ORD.OrderDate >'20090515'

SELECT *
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
AND ORD.OrderDate >'20090515'

Mit der ersten erhalten Sie nur die Datensätze, deren Bestellung nach dem 15. Mai 2009 datiert ist, wodurch die linke Verknüpfung in eine innere Verknüpfung umgewandelt wird.

Der zweite Datensatz enthält diese Datensätze sowie alle Kunden, die keine Bestellungen haben. Die Ergebnismenge ist sehr unterschiedlich, je nachdem, wo Sie die Bedingung setzen. (Select * dient nur als Beispiel, Sie sollten dies natürlich nicht im Produktionscode verwenden).

Die Ausnahme ist, wenn Sie nur die Datensätze in einer Tabelle sehen wollen, aber nicht in der anderen. Dann verwenden Sie die Where-Klausel für die Bedingung und nicht die Verknüpfung.

SELECT *
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
WHERE ORD.OrderID is null

31voto

Bill Karwin Punkte 493880

Die meisten RDBMS-Produkte optimieren beide Abfragen identisch. In "SQL Performance Tuning" von Peter Gulutzan und Trudy Pelzer haben sie mehrere RDBMS-Marken getestet und keinen Leistungsunterschied festgestellt.

Ich ziehe es vor, Join-Bedingungen von Abfragebeschränkungsbedingungen getrennt zu halten.

Wenn Sie Folgendes verwenden OUTER JOIN Manchmal ist es notwendig, Bedingungen in die Join-Klausel aufzunehmen.

17voto

TheTXI Punkte 36691

WHERE filtert, nachdem der JOIN stattgefunden hat.

Filter für den JOIN, um zu verhindern, dass während des JOIN-Prozesses Zeilen hinzugefügt werden.

3voto

Johnno Nolan Punkte 28357

Ich bevorzuge den JOIN, um vollständige Tabellen/Views zu verbinden und dann das WHERE zu verwenden, um das Prädikat der resultierenden Menge einzuführen.

Es fühlt sich syntaktisch sauberer an.

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