也许我会以错误的方式去做。这是我正在尝试做的和我的问题。
我有3张桌子。 资产(计算机,网络设备等) 端口(计算机上的端口,网络设备等) port_connections(有一个port_id_a和port_id_b字段,并将每个端口和每个资产链接在一起)
这实际上只是一种跟踪办公楼中的vlans和网络设备/计算机的方法。
我正在使用最新版本的firebird使用方言3.我假设这不是火鸟问题而只是我的sql问题。
我知道这一定是可能的,因为我可以通过正确的连接(端口到port_connections)来完成它,并在WHERE子句中执行其他连接。这个问题是当我将资产表加入ports表时,正确的连接会丢失。
编辑:这是我正在使用的最新查询,因为旧的查询在这一点上毫无用处。我对这个最新查询的问题是它似乎拉动了通过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移动到ports表中,然后此查询执行我想要的操作。
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 :(得分: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
修改强> 我想我看到这里发生了什么。因为您正在从Connections连接到“端口a”,所以即使之后的INNER JOIN(端口a到资产a)没有匹配,它也将返回这些行,因为RIGHT JOIN的行为方式。要排除未插入的行,我认为您只需要修改WHERE子句:
WHERE
(asset_a.asset_id = 2 OR asset_b.asset_id = 2)
AND asset_a.asset_id IS NOT NULL
这将过滤掉asset_a为NULL的行,即那里没有匹配的行,因为没有插入任何内容。