在 SQL 中正确使用 Count() 和 Sum() 吗?
好的,所以我希望我能很好地解释这个问题,因为我觉得这将是一个很难的问题。
我今天正在使用两张桌子。这些看起来像:
@pset table (PersonID int, SystemID int, EntitlementID int, TargetID int)
@Connector table (TargetName varchar(10), fConnector bit)
第一个表存储的记录告诉我,哦,这个人有这个系统,它由这些权利组成,谁有这些目标。有点复杂,但请跟我一起。第二个存储 TargetName,然后存储该目标在我的不太理论的系统中是否有连接器。
我想做的是合并这两个表,以便我可以看到 @pset 中每行的目标标志。正如您将看到的,这将对我以后有所帮助。
如果系统中的每个权利都有一个连接到目标的连接器(对于所有这些权利,标志都是 true),那么我想知道。
所有其他人都应该进入不同的表。
这就是我试图做的,但没有成功。我需要知道我哪里出错了。希望比我更有经验的人能够回答。
-- 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,但其中一项权利没有连接器!如何将这两行放入第二个查询中?
Ok, so I hope I can explain this question well enough, because I feel like this is going to be a tough one.
I have two tables I'm working with today. These look like:
@pset table (PersonID int, SystemID int, EntitlementID int, TargetID int)
@Connector table (TargetName varchar(10), fConnector bit)
The first table stores records that tell me, oh this person has this system, which is composed of these entitlements, whom have these targets. A little complicated, but stay with me. The second stores the TargetName and then whether or not that target has a connector in my not-so-theoretical system.
What I'm trying to do is merge these two tables so that I can see the target flag for each row in @pset. This will help me later as you'll see.
If each entitlement in a system has a connector to the target (the flag is true for all of them), then I'd like to know.
All the others should go into a different table.
This is what I tried to do, but it didn't work. I need to know where I went wrong. Hopefully someone with more experience than me will be able to answer.
-- 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
and
-- 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
Unfortunately, these do not work :(
Edit
Here is a screenshot showing the problem. Notice ProfileID 1599 has a SystemID of 1126567, but one of the entitlements doesn't have a connector! How can I get both of these rows into the second query? (above)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的基本问题是您正在尝试汇总两个不同的记录集。
初始集合(
SELECT
和GROUP BY
子句)表示您希望集合 [ProfileId、SystemId、EntitlementId、TargetId、fConnector] 中的每个差异都有一条记录。第二组(
HAVING
子句)表示,对于初始集中的每一行,您希望将其COUNT
条记录与连接的SUM
。但是,由于您要求分组到单个标志,因此这会产生每个标志的单行效果(假设一对一关系) 。实际上,你是在说 - '嘿,这个目标是否有联系?是的,我想要它。您似乎想要的是汇总到
SystemId
值。为此,您需要更改SELECT
和GROUP BY
子句以仅包含 [ProfileId, SystemId] 集。这将仅返回所有目标均已“连接”的行(从配置文件和系统键入)。您将无法看到各个权利、目标以及它们是否已连接(您将能够推断它们都已连接/未连接,但是)。编辑:
为了充分披露,以下是您如何获得与原始结果集类似的内容,其中列出了所有
EntitlementId
和TargetId
:这应该为您提供
TargetId
的ProfileId
/SystemRoleId
键列表,其中所有EntitlementId
和TargetId
具有连接(或者,对于并非全部具有连接的情况,将 CTE=
翻转为<>
)。Your basic problem is that you're trying to roll up to two different record sets.
The initial set (the
SELECT
andGROUP BY
clauses) is saying that you want one record for every difference in the set [ProfileId, SystemId, EntitlementId, TargetId, fConnector].The second set (the
HAVING
clause) is saying that you want, for every row in the inital set, to compare it'sCOUNT
of records with theSUM
of the connections. However, because you've asked for grouping down to the individual flag, this has the effect of getting a single row for each flag (assuming 1-to-1 relationships). Effectively, you're saying - 'Hey, if this target has a connection? Yeah, I want it'.What you appear to want is a roll up to the
SystemId
value. To do that, you will need to change yourSELECT
andGROUP BY
clauses to only include the set [ProfileId, SystemId]. This will return only those rows (keyed from profile and system) who has all targets 'connected'. You will not be able to see the individual entitlements, targets, and whether they are connected (you will be able to infer that they will all be/not be connected, however).EDIT:
In the interests of full disclosure, here is how you'd get something similar to your original results set, where it lists all
EntitlementId
s andTargetId
s:This should get you a listing, down to the
TargetId
, ofProfileId
/SystemRoleId
keys where allEntitlementId
s andTargetId
s have a connection (or, flip the CTE=
to<>
for those where not all do).编辑:修复了我原来的查询,也更新了描述
您可以将其拆分:首先找到
fConnector
为 0 的TargetID
然后查找具有与您找到的目标相同的PersonID
、SystemID
对。然后选择相关数据:(这会查找PersonID
、SystemID
对,其中至少一项权利没有连接到目标的连接器)用于查找
的查询PersonID
、SystemID
对(其中所有权利都有一个到目标的连接器)类似:区别在于与临时表的连接(
<>
与<代码>=)。这与零的答案非常相似,但不使用计数或求和。Edit: fixed my original queries, updated the description as well
You can split this up: first find the
TargetID
s that have anfConnector
of 0. Then find thePersonID
,SystemID
pairs that have any target equal to the ones you found. Then select the relevant data: (this finds thePersonID
,SystemID
pair where at least one entitlement does not have a connector to the target)The query to find the
PersonID
,SystemID
pairs where all entitlements have a connector to the target is similar:The difference is in the join with the temp table (
<>
vs=
). This is very similar to zero's answer, but doesn't use counts or sums.