让我说我有桌子:
帐户:id,id2,id3,custId,option1,option2,type
并且同一张表中的所有帐户都有一些" parent"帐户(可以是#34; solo"没有孩子的帐户),有些是"孩子"帐户(我知道设计不好,但那是我正在使用的)。
每个帐户的不同/复合键为id + id2 + id3 + option1 + option2 + custId
。
我想查询" parent"的列表或者"独奏"具有特定custId
和type
的帐户,可以通过以下方式轻松完成:
Select *
From accounts
Where custId = 1 And type = 'foo'
and (option1 = 'solo' Or option2 = 0)
其中'solo'
表示它是一个独立帐户且没有子女,0
表示它是一系列帐户中的第一个,因此也就是其父级。
然后我想获得"孩子的数量"与通过上述查询的结果集获得的每个父关联。显然"独奏"帐户不会有孩子。
例如,获得"孩子"来自特定的父母"帐户会是这样的(让我们说我正在寻找id = 1,id2 = 1,id3 = 1的帐户子女:
Select Count(*)
From accounts
Where id = 1 And id2 = 1 And id3 = 1 And custId = 1
And option1 != 'solo' And option2 != 0)
那么如何组合这两个查询以获得第一个结果集的每个行的计数呢?
示例
填充我们可以拥有的表格:
id id2 id3 custId option1 option2 type
------------------------------------------------------------
1 1 1 1 solo 9 foo
2 2 2 1 solo 9 foo
3 4 4 1 NULL 0 foo
3 4 4 1 NULL 1 foo
3 4 4 1 NULL 2 foo
我想要一个像这样的结果集:
id id2 id3 custId option1 option2 type children
-------------------------------------------------------------------------
1 1 1 1 solo 9 foo 0
2 2 2 1 solo 9 foo 0
3 4 4 1 NULL 0 foo 2
基本上我想要这样的东西(我知道这是错的)
Select *,
(Select count(*) from accounts
Where option1 != 'solo' And option2 != 0
And --all 3 ids and custId equal to the current row
) --this is the part i don't know how to do
From accounts
Where custId = 1 And Type = 'foo' And (option1 = 'solo' Or option2 = 0)
我的大脑正在围绕如何做到这一点。谢谢您的帮助。
答案 0 :(得分:1)
这适用于您的数据:
select a.*
, children = isnull(c.children, 0)
from accounts a
outer apply (select children = count(1)
from accounts c
where a.option1 is null
and a.id = c.id
and a.id2 = c.id2
and a.id3 = c.id3
and a.custId = c.custId
and c.option2 <> 0) c
where (a.option1 = 'solo' or a.option2 = 0)
and a.type = 'foo'
评论后修改:
好的,所以查询的主要部分是WHERE
子句 - 这决定了返回的三行。
一旦我们有这些行,我们需要计算出有多少孩子 - 这就是OUTER APPLY
实现的目标。
基本上,对于每个非独奏行,我们将此匹配到任何子行(即c.option2 <> 0
)并获取这些行的计数,当现在匹配时显式返回0或者它是 'solo'父行。
由于我们仅匹配非独奏父行,因此我们使用a.option1 is null
过滤这些行,即在检查任何匹配之前检查父行option1
值。由于数据的性质,c.option1 is null
也可以,因为父和子非独奏行都有null
option1
值。
count(1)
并不意味着什么;它只是每行计算的任意值,在这种情况下是常量。您可以轻松使用count(*)
。在当天,这可能会对查询处理产生影响,但对于现代RDBMS优化器,您将看不到任何差异。
这是一个替代查询,它采用略有不同的方式:
select a.*
, children = isnull(c.children, 0)
from accounts a
left join (select children = count(*)
, id
, id2
, id3
, custId
from accounts
where option1 is null and option2 <> 0
group by id
, id2
, id3
, custId) c
on a.id = c.id
and a.id2 = c.id2
and a.id3 = c.id3
and a.custId = c.custId
where (a.option1 = 'solo' or a.option2 = 0)
and a.type = 'foo'
因此它分别使用count(*)
和LEFT JOIN
代替count(1)
和OUTER APPLY
。 OUTER APPLY
会应用于查询之外的每一行;您可以将它用于函数,但它也可以帮助代码更简洁,就像在这种情况下一样。只是个人偏好我做出这些选择。