2009-08-19 93 views
2

也许我正在以错误的方式去解决它。这是我想要做的和我的问题。右连接一个表两次到第二个表,每个别名内部连接到一个第三个表的两个别名

我有3张桌子。 资产(计算机,网络设备等) 端口 port_connections(计算机,网络设备等的端口)(具有port_id_a和port_id_b领域和环节的每个端口和用于其各自的资产一起)

这是真的只是一种在办公大楼中跟踪vlans和网络设备/计算机的方法。

我使用最新版本的firebird使用方言3.我假设这不是一个火鸟问题,只是与我的SQL问题。

我知道这一定是可能的,因为我可以用正确的连接(端口连接到port_connections)并在WHERE子句中执行其他连接。与此相关的问题是,当我将资产表加入端口表时,正确的连接会丢失。

编辑:这是我正在使用的最新查询,因为旧的在这一点上是无用的。我对这个最新的查询的问题似乎是通过port_connections表两次拖动链接的项目。所以我会得到正确的port_connections记录,然后我得到一个没有port_connection的单个端口的重复记录。我需要以某种方式摆脱此后的记录,但仍保留没有port_connection记录的其他端口记录。

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 

表: 资产:

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 

港口

PORT_ID 
ASSET_ID 
PORT 
TITLE 
DESCRIPTION 
"TYPE" 
SPEED 

编辑:此修复程序是在CONNECTION_ID进入端口表和日是查询然后做我想要的。

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

是否可以修改您的问题以包含这三个表的模式?我试图理解连接,没有表格布局就难以把它放在一起。 – SqlRyan 2009-08-19 05:37:20

回答

1

我修改了您的查询以便编译,并将其包含在下面。您看到有关意外表名的错误位于INNER JOIN行 - 您再次输入了左表名,而且您不需要,因为SQL使用联接条件(ON子句)来确定左侧表是。

这是否会返回您期望的所有行,或者您是否期望看到一些您不是的结果?

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 

编辑: 我想我明白是怎么回事。由于RIGHT JOIN从Connections连接到“port a”,因为RIGHT JOIN的行为方式,即使稍后INNER JOIN(端口a到资产a)没有匹配,它也会返回这些行。排除那些未插入的行,我想你只需要修改你的WHERE子句:

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

这会过滤掉行针对asset_a为空,即那里没有匹配存在,因为没有被插入。

+0

这工作(减去两个逗号)。我改变了内连接到左连接,现在它似乎关闭,但它获得额外的记录。 例如,我有一台计算机/资产有一个端口和一个port_connection到路由器上的端口。这个新查询会将计算机作为asset_a并将路由器作为asset_b,这是正确的。下一个记录的asset_a为null,计算机又在asset_b下。 看来它在某种程度上交叉连接了连接中的port_id_a和port_id_b,因此即使计算机端口记录仅在port_connections.port_id_a上链接一次,它也会显示两次。 – Blake 2009-08-19 06:43:56

+0

如果你没有加入你的左/右连接中的整个密钥,你会得到额外的记录 - 例如,如果你的密钥是由portname和computername组成的,但你只加入computername,你会有两个记录的端口,它不知道哪一个加入,所以它会返回两个。那是什么发生?为了说明,您可能需要展开您的SELECT列表以包含计算机表中的一些其他字段,以查看哪些字段导致重复项。 – SqlRyan 2009-08-19 17:19:08

+0

我的密钥是端口表上的port_id,以及资产表上的asset_id。对于具有一个端口的单台计算机,它将返回asset_a/port_a作为计算机,asset_b/port_b作为它插入的路由器。下一条记录是asset_b/port_b下的计算机信息的副本,以及null的asset_a/port_a。它出现在哪里(在a或b之下)与我的连接顺序有关,但无论我尝试什么,我都无法摆脱这些重复项。如果我能以某种方式设置一个独特的,所以每个端口只在port_a和port_b别名表之间列出一次。 – Blake 2009-08-19 17:50:47