我有用户,职位和许可证。
关系是:
用户可能有很多许可证
职位可能需要很多执照
因此,我可以轻松获得每个职位的许可证要求以及每个用户的有效许可证。
但是我想知道匹配这两组的最佳方法是什么?随着逻辑的发展,用户至少需要某个职位所需的那些许可证。可能还有更多,但其余的都不相关。
我想获得用户和合格职位的结果。
PersonID PositionID
1 1 -> user 1 is eligible to work on position 1
1 2 -> user 1 is eligible to work on position 2
2 1 -> user 2 is eligible to work on position 1
3 2 -> user 3 is eligible to work on position 2
4 ...
如您所见,我需要为所有用户提供一个结果,而不是每个呼叫一个,这会使事情变得容易得多。
这里实际上有5个表:
create table Person ( PersonID, ...)
create table Position (PositionID, ...)
create table License (LicenseID, ...)
和关系
create table PersonLicense (PersonID, LicenseID, ...)
create table PositionLicense (PositionID, LicenseID, ...)
因此,基本上,我需要找到某个人被许可从事工作的职位。当然,这里还有一个更复杂的问题,因为还有其他因素,但是主要目标是相同的:
如何将一个关系表的多个记录与另一个关系表的多个记录进行匹配。也可以将其描述为每组记录的
inner join
,而不是通常在TSQL中完成的每条记录。我在考虑TSQL语言构造:
行集,但我从未使用过它们,也不知道如何使用它们
intersect
语句虽然可能只适用于整个集合而不适用于组 最佳答案
最终解决方案(以供将来参考)
同时,当其他开发人员回答我的问题时,这是我想到的,并使用了CTE和分区,这些当然可以在SQL Server 2008 R2上使用。我以前从未使用过结果分区,所以我不得不学习一些新知识(加在一起)。这是代码:
with CTEPositionLicense as (
select
PositionID,
LicenseID,
checksum_agg(LicenseID) over (partition by PositionID) as RequiredHash
from PositionLicense
)
select per.PersonID, pos.PositionID
from CTEPositionLicense pos
join PersonLicense per
on (per.LicenseID = pos.LicenseID)
group by pos.PositionID, pos.RequiredHash, per.PersonID
having pos.RequiredHash = checksum_agg(per.LicenseID)
order by per.PersonID, pos.PositionID;
因此,我对以下三种技术进行了比较:
Cross join(由Andriy M撰写)
Table variable(由Petar Ivanov撰写)
校验和-这是这里(由Robert Koritnik,我)
我的人已经按人和位置订购了结果,所以我也将相同的结果添加到其他两个人中以使返回的结果相同。
产生的估计执行计划
校验和:7%
表变量:2%(表创建)+ 9%(执行)= 11%
交叉加入:82%
我还将Table变量版本更改为CTE版本(而不是使用CTE代替表变量),并在最后删除了
order by
并比较了其估计的执行计划。仅供参考,CTE版本为43%,原始版本为53%(10%+ 43%)。