2017-09-12 4 views
2

Ich versuche, eine Abfrage in MS Access 2013 zu schreiben, und die linke Verknüpfung funktioniert nicht ordnungsgemäß. Es verhält sich wie ein normaler Join.MS Access Left Join funktioniert nicht richtig

Hier ist, was ich versuche zu tun.

Meine erste Tabelle [All Category Types] hat eine Spalte [Category Types]. Ich versuche dann, das mit einer Abfrage zu verknüpfen, die zwei Aggregatfelder enthält. Virtuelle Tabelle [Average by Category Type] wird zuerst nach Besitzer und dann nach [Category Type] gruppiert. Weiter ist ein Summenfeld [CountOfIncident: Number].

Was ich will als Ergebnis ist jedes Element in der Tabelle [All Category Types] und dann die richtige [CountOfIncident: Number] where Owner == "France". Dies funktioniert nicht als linker Join. Es zeigt mir nur die Werte in [All Category Types], die einen übereinstimmenden Datensatz in [Average by Category Type] haben.

Wenn ich den Besitzer aus dieser Tabelle entferne und nur nach [Category Type] gruppiere, funktioniert es ganz gut. Gibt es etwas über das Vorhandensein von mehr als einem Feld in der group by-Klausel, die nicht zulässt, dass eine linke Verknüpfung einer Abfrage ordnungsgemäß funktioniert?

SELECT [All Category Types].[Category Type], 
     [Average by Category Type].[CountOfIncident: Number] 
FROM [All Category Types] 
LEFT JOIN [Average by Category Type] 
ON [All Category Types].[Category Type] = [Average by Category Type].[Category Type] 
WHERE ((([Average by Category Type].Owner)="France")); 

Vielen Dank.

+1

Mein 5c: Ich finde Abfragen weniger lesbar, wenn die Spalten Leerzeichen enthalten und maskiert werden müssen. Warum nicht einfach 'SELECT all_category_types.category_type'? Ich finde auch Abfragen weniger lesbar, wenn mehrere Tabellen beteiligt sind, aber keine Tabellen-Aliase verwendet (z. B. SELECT ct.category_type). Ich finde auch weniger lesbare Abfragen mit vielen überflüssigen Klammern. Warum nicht einfach 'WHERE [Durchschnitt nach Kategorie] .Owner =" France "'? Endlich würde ich lieber wo immer möglich Standard-SQL verwenden. Das wären einfache Anführungszeichen für String-Literale: '= 'France'. –

Antwort

2

[Average by Category Type].Owner = "France" kann nur für innere verbundene Datensätze gelten. Für äußere verbundene Datensätze ist [Average by Category Type].Owner null.

Mit Ihrer WHERE-Klausel wird Ihre äußere Verknüpfung in eine innere Verknüpfung umgewandelt. Bewegen Sie den Zustand der ON Klausel:

SELECT 
    [All Category Types].[Category Type], 
    [Average by Category Type].[CountOfIncident: Number] 
FROM [All Category Types] 
LEFT JOIN [Average by Category Type] 
    ON ([Average by Category Type].[Category Type] = [All Category Types].[Category Type] 
    AND [Average by Category Type].Owner = "France"); 

UPDATE: Im Gegensatz zu anderen DBMS MS Access benötigt Klammern für die ON Klausel: JOIN tablename ON (...) statt JOIN tablename ON ....

+0

War gerade dabei, das gleiche vorzuschlagen. Sie können diese 'WHERE'-Anweisung in' WHERE (([Durchschnitt nach Kategorie Typ] .Owner) = "Frankreich")) ODER [Durchschnitt nach Kategorie Typ] ändern. Besitzer IS NULL' –

+0

@Erik von Asmuth: Es ist besser zu Verschieben Sie die Bedingung in die ON-Klausel, zu der sie gehört. Ich habe meine Antwort entsprechend aktualisiert. –

+0

Nicht für MS Access. Es neigt dazu, mit solchen Vergleichen in der 'ON'-Klausel Probleme zu bekommen (für den Anfang funktioniert der Abfragegenerator nicht mehr, aber wenn Abfragen bei mir fehlgeschlagen sind (JOIN-Ausdruck nicht unterstützt, Access ist wählerisch in seinen Joins))). Für andere RDBMS haben Sie Recht. –

1

Die Aussage von Thorsten Kettner ist richtig, dass die WHERE-Klausel die Anweisung im Wesentlichen in das Äquivalent eines INNER JOINs verwandelt hat.

Der Schlüssel zum Arbeiten mit dem LINKEN JOIN besteht darin, die Reihenfolge zu verstehen, in der die Kriterien angewendet werden. JOIN-Kriterien werden immer zuerst angewendet, dann wird die WHERE-Klausel angewendet, nachdem alle Datensätze verknüpft wurden. Da Sie in einem LEFT JOIN alle Datensätze aus der linken Tabelle unabhängig davon möchten, ob die Join-Bedingung erfüllt ist, müssen Sie sicherstellen, dass alle Bedingungen entweder vor oder als Teil der Join-Bedingung angewendet werden.

Wenn Sie Thorstens Antwort mit allen Bedingungen in der Verbindung arbeiten können, schlage ich diesen Ansatz vor. Aber falls Sie Probleme haben (sehr wahrscheinlich mit Access), können Sie auch einige der Bedingungen in einer Unterabfrage anwenden oder WHERE-Kriterien innerhalb der gespeicherten Abfrage hinzufügen [Durchschnitt nach Kategorie]. Vielleicht ist es offensichtlich, aber im Zusammenhang mit der obigen Erklärung bezüglich der Ausführungsreihenfolge ist die Unterabfrage - einschließlich jeglicher Filterung in der WHERE-Klausel - abgeschlossen, bevor der LEFT JOIN angewendet wird.

SELECT 
    [All Category Types].[Category Type], 
    AverageFiltered.[CountOfIncident: Number] 
FROM [All Category Types] 
    LEFT JOIN 
    (SELECT * FROM [Average by Category Type] 
    WHERE [Average by Category Type].Owner = 'France') 
    As AverageFiltered 
    ON [All Category Types].[Category Type] = AverageFiltered.[Category Type]; 
+0

Ich könnte tatsächlich die neueste Bearbeitung von Thorsten Kettners Antwort bekommen, um an einer Beispieldatenbank zu arbeiten. Vielleicht entfernen Sie den Teil über seine Frage. –

+0

@ErikvonAsmuth Nun, in genau diesem Fall habe ich es auch zur Arbeit gebracht. Aber selbst deine Diskussion mit Thorsten hat gezeigt, dass es mit Access oft schwierig sein kann, die Klammer richtig zu schreiben. Im letzten Monat musste ich zwei Abfragen vollständig überarbeiten, da keine Kombination von Klammern bestimmte Join-Bedingungen beheben würde. Da diese Antworten nicht nur dem ursprünglichen Fragesteller zugute kommen, halte ich einen Verweis auf die andere Antwort für gerechtfertigt. Ich gebe ihm gebührende Kreditwürdigkeit und stimme seiner Antwort zu, aber diese Alternative könnte in anderen Fällen kritisch sein. –

+0

Beachten Sie, dass Sie immer den schrecklichen Weg gehen können: 'ON [Durchschnitt nach Kategorie Typ]. [Kategorie Typ] = [Alle Kategorie Typen]. [Kategorie Typ] UND [Durchschnitt nach Kategorie Typ] .Owner = Rechts ([Alle Kategorien Typen]. [Category Type] & "France", 6) 'funktioniert ohne zusätzliche Klammern –