2

Informantsテーブルを対応するものに結合したいHandlers:

 Informants                       Handlers
+------------------------+      +----------------------------------------+
|Name         Type       |      | HandlerID  Name            HandlerType |
|------------ ---------- |      |----------  ----------------------------|
|Ronald Regan Politician |      | 1          J. Edgar        FBI         |
|Sal Vitale   MOB        |      | 2          Charles Cabell  CIA         |
|Elia Kazan   Famous     |      | 3          Allen Dulles    CIA         |
|Mrs. Kravitz Citizen    |      | 7          Joe McCarthy    Congressman |
|White Pawn   Foreign    |      +----------------------------------------+
+------------------------+

私は、あなたが知らせることができる人々のセットを誰が決定するかに応じて、次のルールに従います。

  • 政治家 --> CIA
  • ギャング、著名人 --> FBI
  • 一般市民→地元警察署
  • 外国のエージェント --> NSA に頼ることができます

そこで、情報提供者と情報提供先を照合します。

SELECT 
   Informants.Name AS RatName,
   Informants.Type AS RatType,
   Handlers.Name AS GmanName,
   Handlers.HandlerID 
FROM Informants
   LEFT JOIN Handlers
   ON (
      (Informants.Type IN ('Politician') AND Handlers.HandlerType = 'CIA')
      OR  
      (Informants.Type IN ('MOB', 'Famous') AND Handlers.HandlerType = 'FBI')
      OR
      (Informants.Type IN ('Citizen') AND Handlers.HandlerType = 'Police')
      OR
      (Informants.Type IN ('Foreign') AND Handlers.HandlerType = 'NSA')
 )

そして、私は結果を得る:

RatName           RatType               GmanName        HandlerID
=============     ==============        ==============  =========
Ronald Regan      Politician            Charles Cabell  2
Ronald Regan      Politician            Allen Dulles    3
Sal Vitale        MOB                   J. Edgar        1
Elia Kazan        Famous                J. Edgar        1 
Mrs. Kravitz      Citizen               NULL            NULL
White Pawn        Foreign               NULL            NULL

ここで、Ronald Reganには2 つの構成済みハンドラーがあり、彼が頼ることができることがわかります。その間:

  • クラヴィッツ夫人と
  • ホワイトポーン

通知できるハンドラーがありません。

だから私が今欲しいのは、ハンドラーのフォールバックリストです。Politicianまたはエージェントの場合は、ハンドラーForeignをフォールバックしてください。FBIこれは、理想的には私の結果セットが次のようになることを意味します。

RatName           RatType               GmanName        HandlerID
=============     ==============        ==============  =========
Ronald Regan      Politician            Charles Cabell  2
Ronald Regan      Politician            Allen Dulles    3
Sal Vitale        MOB                   J. Edgar        1
Elia Kazan        Famous                J. Edgar        1 
Mrs. Kravitz      Citizen               NULL            NULL
White Pawn        Foreign               J. Edgar        1

それが私の質問です。以前の参加が何にも一致しなかったという基準に参加する必要があります。


問題

私が回避しようとしている問題は次のとおりです。

  • 主要なケースが結合PoliticiansしますFBI
  • バックアップケースがPoliticians参加CIA

そして、私は次のようなものになります:

RatName           RatType               GmanName        HandlerID
=============     ==============        ==============  =========
Ronald Regan      Politician            Charles Cabell  2
Ronald Regan      Politician            Allen Dulles    3
Ronald Regan      Politician            J. Edgar        1
Sal Vitale        MOB                   J. Edgar        1
Elia Kazan        Famous                J. Edgar        1 
Mrs. Kravitz      Citizen               NULL            NULL
White Pawn        Foreign               J. Edgar        1

そして、Ronald Reganは、報告先がすでにいるときに、新しい「代替」エントリを取得します。

4

3 に答える 3

4

少し遅いと思いますが、お勧めします:

  • 正規化されたスキーマを使用する
  • タイプのルックアップ テーブルを使用して参照する
  • フォールバック ルールに多対多のジャンクション テーブルを使用する
  • 多くのフォールバック オプションを許可する
  • ロジックをコードに入れるのを避け、データに入れる

スキーマ設定スクリプトは次のとおりです。

-- Setup test data
create table InformantTypes (
    Type varchar(20) not null primary key
)
insert into InformantTypes select 'Politician'
insert into InformantTypes select 'MOB'
insert into InformantTypes select 'Famous'
insert into InformantTypes select 'Citizen'
insert into InformantTypes select 'Foreign'

create table HandlerTypes (
    Type varchar(20) not null primary key
)
insert into HandlerTypes select 'FBI'
insert into HandlerTypes select 'CIA'
insert into HandlerTypes select 'Congressman'
insert into HandlerTypes select 'Police'
insert into HandlerTypes select 'NSA'

create table InformantTypesToHandlerTypes (
      InformantType varchar(20) not null references InformantTypes (Type)
    , HandlerType varchar(20) not null references HandlerTypes (Type)
    , Ordinal int not null
)
insert into InformantTypesToHandlerTypes select 'Politician', 'CIA', 1
insert into InformantTypesToHandlerTypes select 'MOB', 'FBI', 1
insert into InformantTypesToHandlerTypes select 'Famous', 'FBI', 1
insert into InformantTypesToHandlerTypes select 'Citizen', 'Police', 1
insert into InformantTypesToHandlerTypes select 'Foreign', 'NSA', 1
insert into InformantTypesToHandlerTypes select 'Politician', 'FBI', 2
insert into InformantTypesToHandlerTypes select 'Foreign', 'FBI', 2

create table Informants (
      Name varchar(50) not null primary key
    , Type varchar(20) not null references InformantTypes (Type)
)
insert into Informants select 'Ronald Regan', 'Politician'
insert into Informants select 'Sal Vitale', 'MOB'
insert into Informants select 'Elia Kazan', 'Famous'
insert into Informants select 'Mrs. Kravitz', 'Citizen'
insert into Informants select 'White Pawn', 'Foreign'

create table Handlers (
      HandlerID int not null primary key
    , Name varchar(50) not null unique
    , HandlerType varchar(20) not null references HandlerTypes (Type)
)
insert into Handlers select 1, 'J. Edgar', 'FBI'
insert into Handlers select 2, 'Charles Cabell', 'CIA'
insert into Handlers select 3, 'Allen Dulles', 'CIA'
insert into Handlers select 7, 'Joe McCarthy', 'Congressman'

実際のクエリは次のとおりです(OPの出力を正確に返します):

-- Actual Query
;with cte as (
    select RatName, RatType, GmanName, HandlerID, DenseRank
    from (
        select
            i.Name AS RatName,
            i.Type AS RatType,
            h.Name AS GmanName,
            h.HandlerID,
            dense_rank() over (partition by i.Name order by ordinal) as DenseRank
        from Informants i
            join InformantTypesToHandlerTypes tt on i.Type = tt.InformantType
            join Handlers h on tt.HandlerType = h.HandlerType
    ) as a
    where DenseRank = 1 -- This bit keeps Reagan from going to the FBI
)
-- Get informants with their first available handler option
select RatName, RatType, GmanName, HandlerID
from cte
-- Get informants with no available handler option
union all
select i.Name, i.Type, null, null
from Informants i
where i.Name not in (select RatName from cte)
order by RatName

ちょっとした説明として、このクエリが行っていることは次のとおりです。

  • OPと同じように、based on に参加Informantsしています。簡単に複数回使用したいので、 CTE内で行っているだけです(CTE は事実上、派生テーブル、テーブル変数、または一時テーブルが同様に簡単に機能する一時的なビューです)。HandlersType
  • 複雑なスイッチ (ビジネス要件が変更された場合に維持する必要がある) でハードコーディングされたルールに基づいて Informant を Handler に結合するのではなく、作成した多対多のジャンクション テーブルに基づいて結合しています。どのユーザーも、適切と思われるルールを簡単に変更できます。
  • 次に、ランキング関数を追加して、利用可能なプライマリおよびフォールバック Handler オプションを知らせます。情報提供者ごとに利用可能な最高ランクのオプションを選択するだけでよいので、不要なフォールバック オプションを不必要に表示することはありません。
  • このデータセットを確立したら、そこから選択して、利用可能なハンドラを持つすべての情報提供者を表示できます。
  • CTE にないインフォーマントを (共用体を使用して) 取得することにより、利用可能なハンドラーを持たない残りのインフォーマントを簡単に取得できるようになりました。

他にも方法はあると思いますが、今回はこんな感じで考えました。

于 2012-10-03T21:30:40.680 に答える
0

まず、次のようにルールを永続化するためにテーブルを追加することをお勧めします

 InformantRules
Type         PrimRatType SecRatType
Politicians   CIA           CIA 
Mobsters      FBI 
Famous        FBI 
Citizens      Police 
Foreign       NSA           CIA

それからあなたは書くことができます

Select i.Name, i.Type, 
   Coalesce (p.Name, s.Name) ContactName
From Informants i
   Join InformantRules r On r.Type = i.Type
   Left Join Handlers p on p.HandlerId 
         = (Select Min(HandlerId) 
            From Handlers 
            Where HandlerType = r.PrimRatType)
   Left Join Handlers s on s.HandlerId 
         = (Select Min(HandlerId) 
            From Handlers 
            Where HandlerType = r.SecRatType)
于 2012-10-03T20:33:56.463 に答える
0

結合条件を少し変更できます。

SELECT 
   Informants.Name AS RatName,
   Informants.Type AS RatType,
   Handlers.Name AS GmanName,
   Handlers.HandlerID 
FROM Informants
   LEFT JOIN Handlers
   ON 
    (
      (Informants.Type IN ('Politician') AND (Handlers.HandlerType = CASE WHEN EXISTS (SELECT TOP 1 1 FROM Handlers WHERE HandlerType = 'CIA') THEN 'CIA' ELSE 'FBI' END))
      OR  
      (Informants.Type IN ('MOB', 'Famous') AND Handlers.HandlerType = 'FBI')
      OR
      (Informants.Type IN ('Citizen') AND Handlers.HandlerType = 'Police')
      OR
      (Informants.Type IN ('Foreign') AND (Handlers.HandlerType = CASE WHEN EXISTS (SELECT TOP 1 1 FROM Handlers WHERE HandlerType = 'NSA') THEN 'NSA' ELSE 'FBI' END))
    )
于 2012-10-03T20:51:50.353 に答える