我想将 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 | +----------------------------------------+
+------------------------+
我遵循的规则取决于谁决定了一组人,你可以告知:
所以我将告密者与他们通知的人匹配到:
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 有两个配置的处理程序,他可以转向。虽然:
他们可以通知没有处理程序。
所以我现在想要的是一个后备的处理程序列表。如果您是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
这是我的问题,我需要加入an earlier join didn't match anything.
的标准我想避免的问题是:
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
罗纳德·里根获得一个新的“后备”条目,当时他已经有人要报告。
答案 0 :(得分:2)
我猜,有点晚了,但我建议:
以下是架构设置脚本:
-- 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
作为一小部分解释,这是这个查询正在做的事情:
Informants
加入Handlers
到Type
。我们只是在CTE内部进行,因为我们想要多次轻松使用它(CTE实际上是一个临时视图,派生表,表变量或临时表可以很容易地工作)。可能有其他方法可以做到这一点,但这次是我的思维过程如何运作。
答案 1 :(得分:1)
您可以稍微改变一下加入条件:
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))
)
答案 2 :(得分: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)