2016-04-11 8 views
1

ich zwei Tabellen haben, wie folgt:Wie bekommen die Verknüpfungen direkt in einer SQL-Abfrage

Menschen:

First_Name Last_Name 
    Bill  Smith 
    David  Williams 
    Fred  Jones 
    Freda  Jones 
    Jane  Smith 
    John  Smith 
    Peter  Williams 
    Sally  Williams 

Haustiere:

Species Title Owner 
    Dog Fido Jones 
    Cat Tibs Jones 
    Dog Jock Williams 

Ich weiß, es ist ein seltsames Datenbankdesign, aber bitte sagen Sie mir nicht, die Datenbank neu zu gestalten. Es ist ein Beispiel, das das eigentliche Problem darstellt, das komplizierter ist und nicht neu gestaltet werden kann.

Ich versuche, eine Abfrage zu formulieren, die genau eine Zeile für jede Person zurück, und eine Spalte mit dem Titel ihrer Katze enthält, oder null, wenn sie nicht eine Katze besitzen (I verwendet Title weil Name ein reserviertes Wort ist und Zugang beschwert).

Die nächst ich komme mit habe, ist:

SELECT People.*, Pets.Title 
FROM People 
LEFT JOIN Pets ON People.Last_Name = Pets.Owner 
WHERE Pets.Species IS NULL OR Pets.Species = "Cat" 

Doch diese Liste keine Zeilen für die Familie Williams, weil sie einen Hund besitzen.

Ich habe dies als MS Access getaggt, weil ich tatsächlich Access 97 verwende (nicht fragen!), Aber, anders als Access 's eher begrenzte Join-Einrichtungen, sollte es eine allgemeine SQL-Frage sein.

+1

Sie ein Problem, wenn (im vollständigen Schema) haben, können Sie nur einen Nachnamen haben (Teilschlüssel) Identifizieren Sie den Besitzer der Katze. Du könntest Menschen haben, die in verschiedenen Häusern leben, beide mit dem Nachnamen Williams. Gemäß Ihrem Schema sind alle ihre Haustiere in gemeinschaftlichem Besitz. – mwigdahl

Antwort

5

EDIT: Die linke Joinsyntax in Access verursacht Probleme, was bedeutet, dass wir für den Zugriff eine Unterabfrage einbeziehen müssen. Das sieht ungefähr so ​​aus (das ungeprüft);

SELECT People.*, Pets.Title 
FROM People LEFT JOIN 
    [SELECT Pets.* FROM Pets WHERE Pets.Species = 'Cat']. AS Pets 
    ON People.Last_Name = Pets.Owner 

- Original Antwort -

Was scheinen Sie ist beitreten regelmäßig links zu wollen, mit einer zusätzlichen Bedingung, dass das Tier eine Katze sein muss;

SELECT People.*, Pets.Title 
FROM People LEFT JOIN Pets 
    ON People.Last_Name = Pets.Owner AND Pets.Species = 'Cat' 

Der Grund für nicht die Katze Zustand in einer WHERE Klausel setzen ist, dass eine where-Klausel alle nicht Einstimmungen eliminiert, während es in der ON Klausel setzt das Ergebnis NULL voll ist, wenn es keine Übereinstimmung finden (genauso wie Sie Ihr gewünschtes Ergebnis zu beschreiben)

+0

Ich habe genau das versucht, aber ich bekomme nur "Join Ausdruck nicht unterstützt". Offenbar ist das in einer ON-Klausel nicht legal. – Dave

+0

@Dave Doh, Zugriffssyntax vs SQL-Syntax ruft mich jedes Mal :) Aktualisierte die Antwort. –

+0

Sie sind ungefähr zur selben Zeit dort wie ich, siehe unten. Vielen Dank. – Dave

1

diese Liste keine Zeilen für die Familie Williams, weil sie besitzen einen Hund

das ist becaus e der WHERE Klausel:

WHERE Pets.Species IS NULL OR Pets.Species = "Cat" 

Wenn Pets.Species ist "Dog" dann falsch bewertet dies würde, so sind diese Aufzeichnungen nicht gezeigt. Entfernen Sie zuerst die Klausel ganz:

SELECT People.*, Pets.Title 
FROM People 
LEFT JOIN Pets ON People.Last_Name = Pets.Owner 

Jetzt sind Sie immer die Aufzeichnungen Sie wollen, aber nicht speziell die Daten Sie wollen. Die Spalte Title zeigt einen beliebigen Wert an und Sie möchten nur "Cat" oder NULL anzeigen.Sie können die JOIN einstellen, dass erreichen:

SELECT People.*, Pets.Title 
FROM People 
LEFT JOIN Pets ON People.Last_Name = Pets.Owner 
       AND Pets.Species = 'Cat' 

Dies filtert die Tabelle verbunden, aber nicht die gesamte Ergebnismenge.

+0

David, ich habe das versucht, siehe Kommentar oben. Vielleicht ist dies eine Schwäche von Access. – Dave

0

Versuchen Sie, diese

SELECT People.*, case when Pets.Species = 'Cat' then Pets.Title else null end as Title 
FROM People LEFT JOIN Pets ON People.Last_Name = Pets.Owner 
+0

Das ist eine nette Idee. Access unterstützt Case nicht, aber ich habe ein Äquivalent mit IIF verwaltet: SELECT People. *, IIF (Pets.Species = 'Katze', Pets.Title, NULL) als Titel, Species VON Leuten LINKS JOIN Pets ON People.Last_Name = Pets.Owner Leider hinterlässt es extra Reihen (für Fred und Freda Jones, die auch einen Hund haben), die ich nicht los werde. – Dave

0

für die Nachwelt - ich habe es endlich:

SELECT People.*, Pets.Title FROM 
People LEFT JOIN (SELECT * FROM Pets WHERE Species='Cat') AS PeopleWithCats 
ON People.Last_Name=PeopleWithCats.Owner 
Verwandte Themen