有条件的区别

时间:2014-04-24 06:34:25

标签: sql sql-server distinct

对不起有点长篇介绍,但我想弄清楚我想做什么。如果有人能够提出更合适的标题,请随时编辑。

我编写了一个SNMP收集器,每小时查询一次数据中心的每个交换机并检查哪些端口在线,并将结果存储在MS SQL 2k12数据库中。其动机是,管理员通常不会报告已停产的服务器或其他设备,而且我们的交换机端口已用完。

数据库架构如下所示(简化屏幕截图):

DB Schema

Interfaces表是Crawls(Crawl = SNMP收集器)表的子表,因为每个交换机的接口数量不是常数,而是在插入或移除线卡时在Crawls之间进行更改。

现在我想写一个查询,它返回每个Switch上的每个接口,它总是有一个ifOperStatus值为2,而且从来没有ifOperStatus为1。

我写了一个包含三个嵌套子查询的查询,读起来很难看,而且很慢。肯定有一种更简单的方法。

我的方法是使用

过滤那些永远不会改变的端口
HAVING        (COUNT(DISTINCT dbo.Interfaces.ifOperStatus) = 1)

而不是在上次爬网期间对ifOperStatus为2的端口列表进行内部连接。正如我所说,丑陋。

因此,DB的样本输出如下所示:

Sample Query

我正在寻找一个返回5-7行的查询,因为ifOperStatus从未改变过,但是因为ifOperStatus被拍打而没有返回3-4行。

2 个答案:

答案 0 :(得分:3)

怎么样

HAVING (MIN(dbo.Interfaces.ifOperStatus) = 2 AND MAX(dbo.Interfaces.ifOperStatus) = 2)

MINMAX并不要求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
    )