Filtertabelle vor dem Anwenden von Left Join


79

Ich habe 2 Tabellen, ich möchte die 1 Tabelle filtern, bevor die 2 Tabellen zusammengefügt werden.

Kundentabelle:

   ╔══════════╦═══════╗
   ║ Customer ║ State ║
   ╠══════════╬═══════╣
   ║ A        ║ S     ║
   ║ B        ║ V     ║
   ║ C        ║ L     ║
   ╚══════════╩═══════╝

Eintragstabelle:

   ╔══════════╦═══════╦══════════╗
   ║ Customer ║ Entry ║ Category ║
   ╠══════════╬═══════╬══════════╣
   ║ A        ║  5575 ║ D        ║
   ║ A        ║  6532 ║ C        ║
   ║ A        ║  3215 ║ D        ║
   ║ A        ║  5645 ║ M        ║
   ║ B        ║  3331 ║ A        ║
   ║ B        ║  4445 ║ D        ║
   ╚══════════╩═══════╩══════════╝

Ich möchte Links beitreten, damit ich alle Datensätze aus der Kundentabelle erhalte, unabhängig davon, ob die Eintragstabelle verwandte Datensätze enthält. Ich möchte jedoch vor dem Join nach Kategorie D in der Eintragstabelle filtern .

Gewünschten Erfolge:

   ╔══════════╦═══════╦═══════╗
   ║ Customer ║ State ║ Entry ║
   ╠══════════╬═══════╬═══════╣
   ║ A        ║ S     ║  5575 ║
   ║ A        ║ S     ║  3215 ║
   ║ B        ║ V     ║  4445 ║
   ║ C        ║ L     ║  NULL ║
   ╚══════════╩═══════╩═══════╝

Wenn ich folgende Abfrage machen würde:

   SELECT Customer.Customer, Customer.State, Entry.Entry
   FROM Customer
   LEFT JOIN Entry
   ON Customer.Customer=Entry.Customer
   WHERE Entry.Category='D'

Dies würde den letzten Datensatz herausfiltern.

Ich möchte also, dass alle Zeilen aus der linken Tabelle in die nach Kategorie D gefilterte Eintragstabelle eingefügt werden.

Vielen Dank für jede Hilfe im Voraus!


Antworten:


111

Sie müssen den WHEREFilter in die JOINBedingung verschieben:

SELECT c.Customer, c.State, e.Entry
FROM Customer c
LEFT JOIN Entry e
   ON c.Customer=e.Customer
   AND e.Category='D'

Siehe SQL Fiddle mit Demo


Wow du bist schnell und effizient! Das macht den Trick, danke für die Hilfe!
Tom Jenkin

8
@ TomJenkin danke, übrigens hast du eine fantastische erste Frage auf der Seite gepostet. Viele Details usw.
Taryn

Vielen Dank - ich denke, ich werde diese Seite genießen, hoffentlich kann ich eines Tages wie Sie einen Beitrag leisten: D
Tom Jenkin

2
@bluefeet, aber beide Ausführungspläne sind gleich, nicht wahr?
Alex Zhukovskiy

1
So wenden Sie die Filterung auf eine Tabelle an, von der der Join vor dem Join abhängt, wenn die where-Bedingungen auf die erste Tabelle verweisen. Zumindest bei einigen meiner Tests habe ich das gesehen. Ich habe diesen Kommentar als Antwort auf den Kommentar von Alex gepostet.
Áxel Costas Pena

27

Sie könnten auch tun:

SELECT c.Customer, c.State, e.Entry
FROM Customer AS c
LEFT JOIN (SELECT * FROM Entry WHERE Category='D') AS e
ON c.Customer=e.Customer

SQL Fiddle hier


3
@ TomJenkin Entschuldigung für die späte Antwort, ich war die ganze Zeit vom Computer weg. Aus Neugier habe ich beide ausgeführt und die Ausführungspläne überprüft. Die Ausführungspläne sind nahezu identisch, aber in dem Maße, in dem beide besser sind, scheint es sich um die Bluefeet-Version zu handeln.
Jeff Rosenberg

Großartig, das hat mich dazu inspiriert, meinen Fall zu reparieren.
Sivann

1

Oder...

SELECT c.Customer, c.State, e.Entry
FROM Customer c
LEFT JOIN Entry e
   ON c.Customer=e.Customer
WHERE e.Category IS NULL or e.Category='D'

In SQL wird die JOIN-Bedingung vor WHERE ausgeführt. In der vorgeschlagenen Lösung wird also die gesamte Tabelle zusammengefügt und das Ergebnis gefiltert - was bei großen Tabellen sehr teuer sein kann. Die beabsichtigte Filterbedingung sollte Teil der JOIN-Bedingung sein, wie in anderen Antworten vorgeschlagen
Omley,

@ Omley Ich denke, Sie sind verwirrt darüber, wie SQL funktioniert. SQL ist deklarativ und nicht prozedural . Die Reihenfolge der Wörter in der Abfrage hat keinen Einfluss auf die Reihenfolge der Operationen . Das liegt am Motor. Wir können anhand eines einfachen Beispiels erkennen, EXPLAINdass MySql diese Abfrage tatsächlich nur geringfügig besser optimiert als die in Taryns Antwort, obwohl dies sicherlich mehr Glück als das Management bedeutet und das Gegenteil für eine andere Engine durchaus zutreffen könnte.
cz
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.