質問

Sorry for the kinda longish introduction, but I want to make clear what I'm trying to do. If someone is able to come up with a more appropriate title, please feel free to edit.

I wrote an SNMP Collector that queries every switch in our data center once per hour and checks which ports are online, and stores the results in a MS SQL 2k12 DB. The motivation was that often admins don't report a discontinued server or some other device and we are running out of switch ports.

The DB schema looks like this (simplified screenshot):

DB Schema

The Interfaces table is a child table to the Crawls (Crawl = Run of the SNMP collector) table as the number of interfaces is not constant for every switch but changes between Crawls, as line cards are inserted or removed.

Now I want to write a query that returns every Interface on every Switch that ALWAYS had an ifOperStatus value of 2 and NEVER had an ifOperStatus of 1.

I wrote a query that has three nested sub-queries, is ugly to read and slow as hell. There sure has to be an easier way.

My approach was to filter the ports that NEVER changed by using

HAVING        (COUNT(DISTINCT dbo.Interfaces.ifOperStatus) = 1)

and than inner-joining against a list of ports that had an ifOperStatus of 2 during the last crawl. Ugly, as I said.

So, a sample output from the DB would look like this:

Sample Query

And I'm looking for a query that returns rows 5-7 because ifOperStatus never changed, but DOES NOT return rows 3-4 because ifOperStatus flapped.

役に立ちましたか?

解決

How about

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

MIN and MAX don't require SQL Server to maintain a set of all values seen so far, just the highest/lowest. This may also avoid the need to join "against a list of ports that had an ifOperStatus of 2 during the last crawl".

他のヒント

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
    )
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top