2017-12-28 33 views
1

ユーザーがアクセスするサービスの依存関係をモデル化しようとしています。私は親/子の隣接リスト形式の表を作成しました。これは、「サービス」がコンポーネント2などに依存するコンポーネント1と依存関係のタイプに依存していることを示しています。完全またはSQL隣接リストのクエリ

部分この画像はレイアウトを示して - 彼らはその後、失敗した場合、全体的なサービスに障害が発生したため、依存関係の画像

enter image description here

コンプ1 & 9は、異なる色です。 Comp 2-9のいずれかが失敗した場合、サービスは継続されますが、弾力性は低下します。

SELECT t1.ReliesOn AS lev1, t2.ReliesOn as lev2, t3.ReliesOn as lev3, t4.ReliesOn as lev4, t5.ReliesOn as lev5, t6.ReliesOn as lev6 
FROM Scratch AS t1 
LEFT JOIN Scratch AS t2 ON t2.CompID = t1.ReliesOn 
LEFT JOIN Scratch AS t3 ON t3.CompID = t2.ReliesOn 
LEFT JOIN Scratch AS t4 ON t4.CompID = t3.ReliesOn 
LEFT JOIN Scratch AS t5 ON t5.CompID = t4.ReliesOn 
LEFT JOIN Scratch AS t6 ON t6.CompID = t5.ReliesOn 
WHERE t1.ReliesOn = 1; 

( - ここ

は、私は、ユーザーがサービスにアクセスできる4種類のオプションを表示することが非常に粗製のクエリを実行することができ、私はテーブル

CREATE TABLE scratch 
( 
    KeyID  int PRIMARY KEY  NOT NULL, 
    CompDesc  varchar(30), 
    CompID  int NOT NULL, 
    ReliesOn  int NOT NULL, 
    RelianceType  varchar(30), 
) 

INSERT scratch SELECT 0, 'Service', 0, 1, 'Full' 
INSERT scratch SELECT 1, 'Component 1', 1, 2, 'Partial' 
INSERT scratch SELECT 2, 'Component 1', 1, 3, 'Partial' 
INSERT scratch SELECT 3, 'Component 1', 1, 4, 'Partial' 
INSERT scratch SELECT 4, 'Component 4', 4, 5, 'Full' 
INSERT scratch SELECT 5, 'Component 5', 5, 6, 'Full' 
INSERT scratch SELECT 6, 'Component 6', 6, 7, 'Partial' 
INSERT scratch SELECT 7, 'Component 6', 6, 8, 'Partial' 
INSERT scratch SELECT 8, 'Component 2', 2, 9, 'Full' 
INSERT scratch SELECT 9, 'Component 3', 3, 9, 'Full' 
INSERT scratch SELECT 10, 'Component 7', 7, 9, 'Full' 
INSERT scratch SELECT 11, 'Component 8', 8, 9, 'Full' 

を作成するために使用したものです申し訳ありませんが、おそらくより良い方法は、クエリを一緒に文字列)

この結果 -

lev1 lev2 lev3 lev4 lev5 lev6 
1  2  9  NULL NULL NULL 
1  3  9  NULL NULL NULL 
1  4  5  6  7  9 
1  4  5  6  8  9 

私がしようとしているのは、失敗したコンプを設定し、サービスがまだ利用可能かどうかを判断できるクエリを作成することです。

Failed  Result 
1   No Service 
2,3   Reduced Resiliency 
3,8   Reduced Resiliency 
2,3,7,8  No Service 

これはちょうど非常に単純な例ですが、私は私がこれを追加する必要があることをより多くのを持っており、ほとんどの場合、サービスの数は同じコンポーネントに依存します。

これで、障害が発生したコンパイルから、パスがまだ存在するかどうかを判断するために、依存関係をどのように上/下/下に移動しますか?

がうまくいけば、これは意味

おかげで明らかに

+0

「コンポーネント9」は「コンポーネント2」などの「エントリポイント」ではないことを誰かが知ることができますか?また、なぜ 'コンポーネント9'がサンプルデータに含まれていないのですか? – danihp

+0

私はあなたの質問を理解するか分からない。これは、失敗した場合にサービスの可用性をモデリングするために使用されます。私はエントリーポイントを知る必要があるとは思わない。 サンプルデータにComp 9が含まれていないため、依存関係はありません。私は追加できると思います INSERTスクラッチSELECT 12、 'Component 9'、9、NULL、NULL –

答えて

0

Recursive CTEsを使用してこれを行うクエリを作成できました。

まず、Iはscratchテーブルに2件のレコードを追加の自由を取った:

INSERT scratch SELECT 12, 'Component 9', 9, 10, 'Full' 
INSERT scratch SELECT 13, 'Users', 10, 10, 'Full' 

これはことを意味する:図に示すよう

  • 9 10(ユーザ)に依存しています
  • 10はそれ自体に依存しています(つまり、この場合、10はターミナルコンポーネントです - これは、サービスが利用可能になっている必要があります)。
  • クエリで

、利用できないコンポーネントは、そのIDがFailedComponents CTEに列挙しておく必要があります

with FailedComponents (id) as (
    select id from (values 
    (1), (7), (8) 
    ) x(id) 
), OnlineComponents (compId, reliesOn) as (
    select compId, reliesOn 
    from scratch 
    where compId = 0 -- <== entry point here 
    union all 
    select s.compId, s.reliesOn 
    from scratch s 
    join OnlineComponents c 
    on s.compId = c.reliesOn 
    where s.compId not in (select id from FailedComponents) 
) 
select case 
    when exists (select * from OnlineComponents where compId = reliesOn) 
    then 'Service is available' 
    else 'No Service' 
    end as [Status] 
; 

ここでは、クエリがそれらをどのように処理するかを確認するために、異なる値を試してみることができますSQL Fiddleです。

scratchテーブルで指定されている信頼タイプは、Full/Partialではありません。依存タイプはコンテキストから推定されます。基本的に、使用可能なコンポーネントのみを歩いてグラフを0から10に渡す方法がある場合、サービス全体が利用可能です。

また、再帰的なCTEの深さには限界があります。これはMAXRECURSIONと呼ばれ、デフォルト値は100です。必要に応じてより高い値に変更する必要があります。

0

を行い、結果のクエリは簡単なものではありません。

with 
from_to as (select 9 as [from], 1 as [to]), 
failed_nodes as (select 3 as f union select 4), --list of failed nodes 
cte as (
    select * 
      ,CAST(CompID AS VARCHAR(255)) AS Path 
    from scratch 
    where CompId = (select [from] from from_to) -easy: ReliesOn is null 
    union all 
    select s.* 
      ,CAST(Path + '.' + CAST(s.CompID AS VARCHAR(255)) AS VARCHAR(255)) 
    from scratch s 
    inner join cte on s.ReliesOn = cte.CompID 
    where s.compid not in (select * from failed_nodes) 
) 
select * from cte 
:生きているパスを把握するためにここで

CREATE TABLE scratch 
( 
    KeyID  int PRIMARY KEY  NOT NULL, 
    CompDesc  varchar(30), 
    CompID  int NOT NULL, 
    ReliesOn  int  NULL, --null to allow node 9 
    RelianceType  varchar(30), 
) 

INSERT scratch SELECT 0, 'Service', 0, 1, 'Full' 
INSERT scratch SELECT 1, 'Component 1', 1, 2, 'Partial' 
INSERT scratch SELECT 2, 'Component 1', 1, 3, 'Partial' 
INSERT scratch SELECT 3, 'Component 1', 1, 4, 'Partial' 
INSERT scratch SELECT 4, 'Component 4', 4, 5, 'Full' 
INSERT scratch SELECT 5, 'Component 5', 5, 6, 'Full' 
INSERT scratch SELECT 6, 'Component 6', 6, 7, 'Partial' 
INSERT scratch SELECT 7, 'Component 6', 6, 8, 'Partial' 
INSERT scratch SELECT 8, 'Component 2', 2, 9, 'Full' 
INSERT scratch SELECT 9, 'Component 3', 3, 9, 'Full' 
INSERT scratch SELECT 10, 'Component 7', 7, 9, 'Full' 
INSERT scratch SELECT 11, 'Component 8', 8, 9, 'Full' 
INSERT scratch SELECT 12, 'Component 9', 9, Null, 'Full' --node 9 added 

クエリを:私はあなたがSQL Fiddle

MS SQL Serverの2014スキーマのセットアップにそれで遊ぶことができ、あなたにアプローチを投稿します

keyID = 0Resultsにチェックすると、サービスがまだ利用可能かどうかを知ることができます。彼は生きているパス(シンプルwhereですが):

| KeyID | CompDesc | CompID | ReliesOn | RelianceType | Path | 
|-------|-------------|--------|----------|--------------|---------| 
| 12 | Component 9 |  9 | (null) |   Full |  9 | 
|  8 | Component 2 |  2 |  9 |   Full |  9.2 | 
| 10 | Component 7 |  7 |  9 |   Full |  9.7 | 
| 11 | Component 8 |  8 |  9 |   Full |  9.8 | 
|  7 | Component 6 |  6 |  8 |  Partial | 9.8.6 | 
|  5 | Component 5 |  5 |  6 |   Full | 9.8.6.5 | 
|  6 | Component 6 |  6 |  7 |  Partial | 9.7.6 | 
|  5 | Component 5 |  5 |  6 |   Full | 9.7.6.5 | 
|  1 | Component 1 |  1 |  2 |  Partial | 9.2.1 | 
|  0 |  Service |  0 |  1 |   Full | 9.2.1.0 < still alive 

RelianceTypeノードに対処するためにあなたのシナリオにこのソリューションを適応させます。

関連する問題