2009-08-19 8 views
2

Vielleicht gehe ich in die falsche Richtung. Hier ist, was ich versuche zu tun und mein Problem.Richtig Join einer Tabelle zweimal zu einer zweiten Tabelle mit jedem Alias ​​inneren Join zu den Aliasen einer dritten Tabelle

Ich habe 3 Tabellen. Vermögen (ein Computer, Netzwerkgerät, usw.) Ports (ein Port auf dem Computer, Netzwerkgerät, usw.) port_connections (hat ein port_id_a und port_id_b Feld und Links jeden Port und dafür jedes Asset zusammen)

Es ist wirklich nur eine Möglichkeit, VLANs und Netzwerkgeräte/Computer in Bürogebäuden zu verfolgen.

Ich benutze die neueste Version von Firebird mit Dialekt 3. Ich gehe davon aus, dass dies kein Problem mit Firebird und nur ein Problem mit meinem SQL ist.

Ich weiß, dass dies möglich sein muss, weil ich es mit genau richtigen Joins (Ports zu port_connections) tun kann und die anderen Joins in der WHERE-Klausel tun. Das Problem dabei ist, dass die Joins verloren gehen, wenn ich die Assets-Tabelle mit der Port-Tabelle verbinde.

EDIT: Dies ist die neueste Abfrage, mit der ich arbeite, weil die alten an dieser Stelle nutzlos sind. Mein Problem mit dieser neuesten Abfrage ist, dass es Elemente zu ziehen scheint, die über die Tabelle port_connections zweimal verbunden sind. So werde ich den richtigen Port Verbindungs-Datensatz bekommen und dann bekomme ich einen doppelten Datensatz mit nur dem einzigen Port ohne Port-Verbindung. Ich muss diesen späteren Datensatz irgendwie loswerden, aber behalte immer noch die anderen Hafendatensätze, die keinen port_connection Datensatz haben.

SELECT 
port_connections.connection_id, 

asset_a.name AS asset_a_name, 
port_a.port AS port_a_name, 
port_a.asset_id as asset_a, 

asset_b.name AS asset_b_name, 
port_b.port AS port_b_name, 
port_b.asset_id as asset_b, 

port_connections.description 

FROM 
port_connections 

right JOIN ports AS port_a 
ON port_connections.port_id_a = port_a.port_id 

right JOIN ports AS port_b 
ON port_connections.port_id_b = port_b.port_id 

left JOIN assets as asset_a 
ON asset_a.asset_id = port_a.asset_id 

left JOIN assets as asset_b 
ON asset_b.asset_id = port_b.asset_id 



WHERE 
(port_a.asset_id = 2 OR port_b.asset_id = 2) 
ORDER BY port_a_name, port_b_name 

Tables: Vermögen:

ASSET_ID 
SYS_ID 
LOCATION_ID 
NAME 
DESCRIPTION 
"TYPE" 
AQUIRED 
DISPOSED 
MFG_NAME 
TAG_NO 

port_connections

"CONNECTION_ID" 
PORT_ID_A 
PORT_ID_B 
DESCRIPTION 

Häfen

PORT_ID 
ASSET_ID 
PORT 
TITLE 
DESCRIPTION 
"TYPE" 
SPEED 

EDIT: Das Update war die connection_id in den Häfen Tisch und th zu bewegen ist Abfrage dann macht was ich wollte.

SELECT 
port_connections.connection_id, 

asset_a.name AS asset_a_name, 
port_a.port AS port_a_name, 
port_a.asset_id as asset_a, 

asset_b.name AS asset_b_name, 
port_b.port AS port_b_name, 
port_b.asset_id as asset_b, 

port_connections.description 

FROM 
port_connections 



right JOIN ports AS port_b 
ON port_connections.connection_id = port_b.connection_id 

right JOIN ports AS port_a 
ON port_connections.connection_id = port_a.connection_id 

left JOIN assets as asset_a 
ON asset_a.asset_id = port_a.asset_id 

left JOIN assets as asset_b 
ON asset_b.asset_id = port_b.asset_id 

WHERE 

port_a.asset_id = 2 
AND 
(port_b.asset_id != 2 or port_b.asset_id is null) 

ORDER BY port_a_name 
+0

Wäre es möglich, Ihre Frage so zu ändern, dass sie das Schema dieser drei Tabellen enthält? Ich versuche, die Joins zu verstehen, und es ist schwer, ohne ein Tabellenlayout zu kombinieren. – SqlRyan

Antwort

1

Ich habe Ihre Abfrage so kompiliert, und fügte sie unten ein. Der Fehler, den Sie über den unerwarteten Tabellenname sehen, befindet sich in der Zeile INNER JOIN - Sie haben den Namen der linken Tabelle erneut angegeben, und Sie müssen dies nicht tun, da SQL die Verknüpfungskriterien (die ON-Klausel) verwendet Tisch ist.

Gibt dies alle Zeilen zurück, die Sie erwarten, oder erwarten Sie einige Ergebnisse, die Sie nicht sind?

SELECT 
port_connections.connection_id, 

asset_a.name AS asset_a_name, 
port_a.port AS port_a_name, 
port_a.asset_id as asset_a, 

asset_b.name AS asset_b_name, 
port_b.port AS port_b_name, 
port_b.asset_id as asset_b, 

port_connections.description 

FROM 
port_connections 
RIGHT JOIN ports AS port_a 
ON port_connections.port_id_a = port_a.port_id 

RIGHT JOIN ports AS port_b 
ON port_connections.port_id_b = port_b.port_id 

INNER JOIN assets as asset_a 
ON asset_a.asset_id = port_a.asset_id 

INNER JOIN assets as asset_b 
ON asset_b.asset_id = port_b.asset_id 

WHERE 
(asset_a.asset_id = 2 OR asset_b.asset_id = 2) 

ORDER BY port_a_name, port_b_name 

EDIT: Ich glaube, ich sehe, was hier vor sich geht. Da Sie RIGHT JOIN von Connections zu "Port a" sind, wird es diese Zeilen auch dann zurückgeben, wenn der INNER JOIN später (Port a zu Asset a) keine Übereinstimmung hat, da sich RIGHT JOIN verhält. Um die Zeilen auszuschließen, die nicht angeschlossen sind, ich glaube, Sie brauchen nur zu ändern, um Ihre WHERE-Klausel:

WHERE 
(asset_a.asset_id = 2 OR asset_b.asset_id = 2) 
    AND asset_a.asset_id IS NOT NULL 

Dies wird Zeilen herauszufiltern, für die asset_a NULL ist, das heißt, wo es keine Übereinstimmung gibt, weil nichts ist eingesteckt.

+0

Das funktionierte (minus die zwei Kommas). Ich habe die Inner joins zu Left joins geändert und jetzt scheint es eng zu sein, aber es bekommt zusätzliche Datensätze. Zum Beispiel habe ich einen Computer/Asset mit einem Port und einem Port_connection zu einem Port auf einem Router. Diese neue Abfrage gibt mir den Computer als Asset_a und den Router als Asset_b, das ist richtig. Der nächste Datensatz hat Asset_a null und der Computer wieder unter Asset_b. Es scheint irgendwie Port_id_a und port_id_b im Join zu verbinden, so dass es zweimal angezeigt wird, obwohl der Computer-Port-Datensatz nur einmal auf port_connections.port_id_a verknüpft ist. – Blake

+0

Sie würden zusätzliche Datensätze erhalten, wenn Sie nicht auf den gesamten Schlüssel in einem Ihrer Links/Rechts-Joins zugreifen würden - wenn Ihr Schlüssel beispielsweise aus Portname und Computername besteht, aber nur aus Computername habe zwei Datensätze für den Port und es würde nicht wissen, welchem ​​man beitreten würde, also würde es beide zurückgeben. Ist das was passiert? Um zu sagen, müssen Sie möglicherweise Ihre SELECT-Liste erweitern, um einige zusätzliche Felder aus Ihrer Computertabelle einzubeziehen, um zu sehen, welche Felder die Duplikate verursachen. – SqlRyan

+0

Meine Schlüssel sind port_id in der Tabelle ports und Asset_id in der Tabelle acres. Für einen einzelnen Computer mit einem Port gibt es Asset_a/Port_a als Computer, Asset_b/Port_b als den Router zurück, an den es angeschlossen ist. Der nächste Datensatz ist ein Duplikat der Computerinformationen unter Asset_b/Port_b und ein Null Asset_a/Port_a. Wo es auftaucht (unter a oder b), hat mit der Reihenfolge meiner Joins zu tun, aber egal was ich versuche, ich kann diese Duplikate nicht loswerden. Wenn ich irgendwie ein distinct setzen könnte, wird jeder Port nur einmal zwischen port_a und port_b Alias-Tabellen aufgeführt. – Blake