2

我们正在监控网络设备。一个设备可能出现在多个交换机上。

我们想要过滤掉那些在上行链路/端口通道上的设备,以防它也出现在另一个端口上。选择所有其他设备。

假设表格如下所示:

HOST,  SWITCH,  PORT
HostA, Switch1, 01
HostB, Switch1, 02
HostA, Switch2, Po  - Po is portchannel / uplink
HostC, Switch2, Po  - Po is portchannel / uplink

期望的输出:

HostA, Switch1, 01
HostB, Switch1, 02
HostC, Swtich2, Po  - is only on an uplink / so that is OK

条目 HostA、Switch2、Po 需要过滤掉,因为它也出现在另一个端口上。

现在的问题是如何编写有效的查询。

在 SQL 术语中,我们希望选择除 HOST 出现两次之外的所有行。然后我们只想要 PORT 不是 'Po' 的那一行

由于子查询,我们当前的查询很慢!?我假设子查询正在创建一个笛卡尔积 - 对吧?

SELECT * FROM devices t1
WHERE NOT ((Port = 'Po') AND 
      ((Select count(*) from table t2 where t1.host=t2.host AND NOT Port='Po') > 0))

同样的问题是如何编写更快的 SQL 查询?

4

3 回答 3

1
SELECT HOST as HOST,  SWITCH,  PORT from table 
WHERE port<>'po' 
UNION ALL
SELECT MAX(HOST) as HOST,  SWITCH,  PORT from table
WHERE port='po'
GROUP BY SWITCH,  PORT 
于 2012-07-24T09:28:37.757 回答
0

不存在应该比相关计数更快(*)

select *
  from devices t1
 where (port <> 'Po'
        or not exists (select null
                         from devices t2
                        where t2.host = t1.host
                          and t2.Port <> 'Po')
       )

更新:如果您认为加入版本会表现更好:

select t1.*
  from devices t1
  left join devices t2
    on t1.host = t2.host
   and t2.port <> 'Po'
 where (t1.port <> 'Po'
    or t2.port is null)

查询自连接设备表,从第二个实例中删除 Po。然后它继续选择所有非 Po 和 Po 而不匹配非 Po。哦,好解释。

于 2012-07-24T09:28:59.813 回答
0

假设主机/交换机组合上最多有一个端口,您可以使用 group by:

select HOST, SWITCH,
       (case when max(case when PORT <> 'Po' then 1 else 0 end) = 1
             then max(case when PORT <> 'Po' then port end)
             else 'Po'
        end) port
from t
group by host, switch

如果你有一个支持 windows 功能的数据库,你可以使用:

select t.host, t.switch, t.port
from (select t.*,
             sum(isPo) over (partition by host, switch) as numPo,
             count(*) over (partition by host, switch) as numAll
      from (select t.*,
                   (case when port = 'po' then 1 else 0 end) as isPo
            from t
           ) t
     ) t
where numPo = numAll or -- all are Po
      (port <> 'Po')    -- remove any other Pos
于 2012-07-24T13:32:18.250 回答