好的,所以我希望我能够很好地解释这个问题,因为我觉得这将是一个艰难的问题。
我今天有两张桌子。这些看起来像:
@pset table (PersonID int, SystemID int, EntitlementID int, TargetID int)
@Connector table (TargetName varchar(10), fConnector bit)
第一个表存储了告诉我的记录,哦,这个人有这个系统,由这些权利组成,他们有这些目标。有点复杂,但留在我身边。第二个存储TargetName,然后存储该目标是否在我不太理论的系统中具有连接器。
我要做的是合并这两个表,以便我可以在@pset中看到每一行的目标标志。这将有助于我后来,你会看到。
如果系统中的每个权利都有一个到目标的连接器(标志为真,对于所有这些),那么我想知道。
所有其他人应该进入另一张桌子。
这是我试图做的,但它不起作用。我需要知道我哪里出错了。希望有比我更多经验的人能够回答。
-- If the count(123) = 10 (ten rows with SystemID = 123) and the sum = 10, cool.
select pset.*, conn.fConnector from @pset pset
inner join vuTargets vt
on vt.TargetID = pset.TargetID
inner join @conn conn
on conn.TargetName = vt.TargetName
group by ProfileID, SystemRoleID, EntitlementID, TargetID, fConnector
having count(SystemID) = sum(cast(fConnector as int))
order by ProfileID
和
-- If the count(123) = 10 (ten rows with SystemID = 123) and the sum <> 10
select pset.*, conn.fConnector from @pset pset
inner join vuTargets vt
on vt.TargetID = pset.TargetID
inner join @conn conn
on conn.TargetName = vt.TargetName
group by ProfileID, SystemRoleID, EntitlementID, TargetID, fConnector
having count(SystemID) <> sum(cast(fConnector as int))
order by ProfileID
不幸的是,这些不起作用:(
修改
以下是显示问题的屏幕截图。注意ProfileID 1599的SystemID为1126567,但其中一个权利没有连接器!如何将这两行都放入第二个查询? (上图)
答案 0 :(得分:2)
您的基本问题是您正在尝试累积到两个不同的记录集
初始集(SELECT
和GROUP BY
子句)表示您希望集合[ProfileId,SystemId,EntitlementId,TargetId,fConnector]中的每个差异都有一条记录。
第二组(HAVING
子句)表示您希望 inital set 中的每一行都将COUNT
个记录与SUM
进行比较的联系。但是,因为您已经要求分组到单个标志,这会为每个标志获取单行(假设为1对1关系) 。实际上,你说 - '嘿,如果这个目标有连接?是的,我想要它。
您希望想要的内容是SystemId
值。为此,您需要将SELECT
和GROUP BY
子句更改为仅包含[ProfileId,SystemId]集。这将仅返回所有目标“已连接”的行(从配置文件和系统键入)。您不能够看到各个权利,目标以及它们是否已连接(您将能够推断它们将全部/不连接,但是)。
编辑:
为了充分披露,以下是您如何获得与原始结果集类似的内容,其中列出了所有EntitlementId
和TargetId
s:
WITH all_connections as (SELECT pset.ProfileId, pset.SystemRoleId
FROM @pset pset
INNER JOIN vuTargets vt
ON vt.TargetId = pset.TargetId
INNER JOIN @conn conn
ON conn.TargetName = vt.TargetName
GROUP BY pset.ProfileId, pset.SystemRoleId
HAVING COUNT(pset.SystemRoleId)
= SUM(CAST(fConnector as INT)))
SELECT pset.*
FROM @pset pset
JOIN all_connections conn
ON conn.ProfileId = pset.ProfileId
AND conn.SystemRoleId = pset.SystemRoleId
这会为您提供TargetId
/ ProfileId
个SystemRoleId
个列表的列表,其中所有EntitlementId
和TargetId
都有连接(或者,将CTE =
翻转为<>
,以便那些不是全部的人。{/ p>
答案 1 :(得分:1)
编辑修复了原始查询,同时更新了说明
您可以拆分:首先找到TargetID
为0的fConnector
。然后找到任意目标等于的PersonID
,SystemID
对你找到的那些。然后选择相关数据:(这会找到PersonID
,SystemID
对,其中至少有一个权利没有到目标的连接器)
with abc as (
select PersonID, SystemID
from pset P
where TargetID in (
select TargetID
from vuTargets V join connector C on V.TargetName = C.TargetName
where C.fConnector = 0
)
)
select P.PersonID, P.SystemID, P.EntitlementID, P.TargetID, C.fConnector
from pset P
join abc on ((P.PersonID = abc.PersonID) and (P.SystemID = abc.SystemID))
join vuTargets V on P.TargetID = V.TargetID
join connector C on V.TargetName = C.TargetName
查找PersonID
,SystemID
对的查询,其中所有权利都具有到目标的连接器类似:
with abc as (
select PersonID, SystemID
from pset P
where TargetID in (
select TargetID
from vuTargets V join connector C on V.TargetName = C.TargetName
where C.fConnector = 0
)
)
select P.PersonID, P.SystemID, P.EntitlementID, P.TargetID, C.fConnector
from
pset P
join abc on ((P.PersonID <> abc.PersonID) or (P.SystemID <> abc.SystemID))
join vuTargets V on P.TargetID = V.TargetID
join connector C on V.TargetName = C.TargetName
区别在于与临时表的联接(<>
vs =
)。这与零的答案非常相似,但不使用计数或总和。