对不起有点长篇介绍,但我想弄清楚我想做什么。如果有人能够提出更合适的标题,请随时编辑。
我编写了一个SNMP收集器,每小时查询一次数据中心的每个交换机并检查哪些端口在线,并将结果存储在MS SQL 2k12数据库中。其动机是,管理员通常不会报告已停产的服务器或其他设备,而且我们的交换机端口已用完。
数据库架构如下所示(简化屏幕截图):
Interfaces表是Crawls(Crawl = SNMP收集器)表的子表,因为每个交换机的接口数量不是常数,而是在插入或移除线卡时在Crawls之间进行更改。
现在我想写一个查询,它返回每个Switch上的每个接口,它总是有一个ifOperStatus值为2,而且从来没有ifOperStatus为1。
我写了一个包含三个嵌套子查询的查询,读起来很难看,而且很慢。肯定有一种更简单的方法。
我的方法是使用
过滤那些永远不会改变的端口HAVING (COUNT(DISTINCT dbo.Interfaces.ifOperStatus) = 1)
而不是在上次爬网期间对ifOperStatus为2的端口列表进行内部连接。正如我所说,丑陋。
因此,DB的样本输出如下所示:
我正在寻找一个返回5-7行的查询,因为ifOperStatus从未改变过,但是因为ifOperStatus被拍打而没有返回3-4行。
答案 0 :(得分:3)
怎么样
HAVING (MIN(dbo.Interfaces.ifOperStatus) = 2 AND MAX(dbo.Interfaces.ifOperStatus) = 2)
MIN
和MAX
并不要求SQL Server维护到目前为止看到的所有值的集合,只是最高/最低值。这也可以避免在最后一次抓取期间加入"以及ifOperStatus为2的端口列表。
答案 1 :(得分:0)
select
s.Hostname,
s.sysDescr,
i.ifOperStatus,
i.ifAllias,
i.ifIndex,
i.ifDescr
from
interfaces i
join crawl c on c.id = i.crawlId
join switches s on s.id = c.switchId
where
i.ifOperStatus = 2
and not exists
(
select 'x'
from
interfaces ii
join crawl cc on cc.id = ii.crawlId
join switches ss on ss.id = cc.switchId
where
s.id = ss.id
and ii.ifOperStatus = 1
)