2

ネットワークデバイスを監視しています。1 つのデバイスが複数のスイッチに表示される場合があります。

別のポートにも表示される場合に備えて、アップリンク/ポートチャネルにあるデバイスを除外したいと考えています。他のすべてのデバイスが選択されます。

テーブルが次のようになっているとします。

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 が 2 回出現する行を除くすべての行を選択します。次に、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)

クエリはデバイス テーブルを自己結合し、2 番目のインスタンスから Po を削除します。次に、非 Po と一致しないすべての非 Po と Po の選択に進みます。うーん、なんという説明。

于 2012-07-24T09:28:59.813 に答える
0

ホスト/スイッチの組み合わせに最大 1 つのポートがあると仮定すると、次の方法でグループを使用できます。

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 に答える