我想将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 有两个个配置好的处理程序可以求助。同时:
- 夫人。克拉维茨和
- 白色棋子
没有可以通知的处理程序。
所以我现在想要的是处理程序的后备列表。如果您是政客
或外国
特工,我们希望您求助于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. 的标准
问题
我试图避免的问题是:
- 主要案件将
政客
加入FBI
- 备用案例将
政治家
加入到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
而罗纳德·里根得到了一个新的“后备”条目,当时他已经有人要向其汇报了。
最佳答案
我想有点晚了,但我建议:
- 使用标准化架构
- 使用类型查找表并引用它们
- 使用多对多联结表作为后备规则
- 允许多种后备选项
- 避免将逻辑放入代码中 - 在数据中进行
这是架构设置脚本:
-- 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一样,我们根据
类型
将Informants
加入到Handlers
。我们只是在 CTE 内做这件事。因为我们希望轻松地多次使用它(CTE 实际上是一个临时 View ,派生表、表变量或临时表也可以轻松工作)。 - 我们不是基于复杂开关中的硬编码规则(如果业务需求发生变化就必须维护)将信息者连接到处理程序,而是基于我们创建的多对多联结表。任何用户现在都可以轻松更改他们认为合适的规则。
- 然后,我们添加一个排名函数,让我们知道可用的主要和后备处理程序选项。我们可以简单地为每个举报人选择排名最高的选项,这样我们就不会不必要地显示不必要的后备选项。
- 一旦建立了这组数据,我们就可以从中进行选择,以显示所有具有可用处理程序的举报人。
- 现在可以通过获取(使用联合)任何不在 CTE 中的 Informant 来轻松获取没有可用处理程序的剩余 Informant。
可能还有其他方法可以做到这一点,但这就是我这次的思考过程。
关于sql-server - 如何连接到一张表并回退到另一张表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12716378/