我们正在监控网络设备。 设备可能出现在多个交换机上。
我们想要过滤掉上行链路/端口通道上的那些设备,以防它出现在另一个端口上。选择所有其他设备。
假设表格如下:
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
Entry 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查询?
答案 0 :(得分: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
答案 1 :(得分: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。哦,这是一个什么解释。
答案 2 :(得分: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