Sql server 具有特定起点和内部联接的cte递归查询
假设我有以下模式:Sql server 具有特定起点和内部联接的cte递归查询,sql-server,sql-server-2008,tsql,jdbctemplate,Sql Server,Sql Server 2008,Tsql,Jdbctemplate,假设我有以下模式: person (person_id, person_account, name) relationships (person_id, father_id) purchases(person_account, total, type) 免责声明:我没有设计这个模式,我知道这很糟糕,所以我道歉。这也是一个例子,这要复杂得多。还要注意,这是我将在JDBCTemplate中使用的查询,这就是我包含标记的原因 现在我想计算一个人的购买量,他或她的儿子购买,他们的儿子购买等等。我想要一
person (person_id, person_account, name)
relationships (person_id, father_id)
purchases(person_account, total, type)
免责声明:我没有设计这个模式,我知道这很糟糕,所以我道歉。这也是一个例子,这要复杂得多。还要注意,这是我将在JDBCTemplate中使用的查询,这就是我包含标记的原因
现在我想计算一个人的购买量,他或她的儿子购买,他们的儿子购买等等。我想要一个关于最初的人的特定起点
与我目前看到的示例不同的是:
个人账户
)purchases
没有person\u id
字段,因此使事情复杂化计数
,而不是其他东西购买
的类型
进行筛选person
表中包含father\u id
字段关系表中没有条目。这将使情况更加复杂
然而,我在理解起点和终点方面存在问题。我的起点可以有一个父亲,所以不能为空。我的端点应该从在
关系表中没有条目的人那里获得购买
所以我想的是:
declare @id int = 234
;with CTEexample as (
select p.person_account, p.person_id, p.type, r.father_id from purchases as s
join person p on p.person_account = s.person_account
join relationships r on r.person_id = p.person_id
where r.person_id = @id
union all
select p.person_account, p.person_id, p.type, r_father_id from purchases as s
join person p on p.person_account = s.person_account
join relationships r on r.person_id = p.person_id
join CTEexample c on p.person_id = r.father_id
)
select count(*) from CTEexample
where type = 's'
然而,它根本不起作用
任何帮助都将不胜感激。保持递归简单(其他人更容易管理),并使用它获取关系。从那里,您可以加入到Person以获得帐号,然后购买
DECLARE @PersonID INT = 1
;WITH Family (PersonID, FatherID) AS (
SELECT p.PersonID, null
FROM Person p
WHERE p.PersonID = @PersonID
UNION ALL
SELECT p.PersonID, r.FatherID
FROM Person p
INNER JOIN Relationships r
ON r.PersonID = p.PersonID -- Me
INNER JOIN Family f
ON f.PersonID = r.FatherID -- Father
)
SELECT *
FROM Family f
JOIN Person p
ON p.PersonID = f.PersonID
JOIN Purchases ps
ON ps.PersonAccount = p.PersonAccount
WHERE ps.Type is null
您有一个非常详细的问题,但我猜您在递归CTE中的谓词正在造成严重破坏。通常,您需要通过递归和查找树来做两件重要的事情:
您需要知道您处于“位置”的级别(在我的示例中为pos)
您需要根据递归中的位置确定关系,以使递归有意义。否则,您将再次显示相同的值,而不会真正使用它所能做的递归功能
以下是一个可能适用于您的示例:
会给你一个层次结构
将找到树的最远横档(最低位置)
将后代和子代的顺序添加到一起
递归的最大好处不是一个或两个级别,而是当您达到5个或更多级别时,能够告诉表达式您想要它的哪一部分。当我做递归时,我通常做两个cte,一个做递归,另一个求最大递归,然后告诉我。否则,每个人都会带着不同等级的继承权回来。除非你真的想要,否则你应该用一个窗口表达式来限制它
我希望这会有所帮助,有时您必须为自己的情况定制一段时间的递归CTE:
Declare @table table ( PersonId int identity, PersonName varchar(512), Account int, ParentId int, Orders int);
insert into @Table values ('Brett', 1, NULL, 1000),('John', 1, 1, 100),('James', 1, 1, 200),('Beth', 1, 2, 300),('John2', 2, 4, 400);
select
PersonID
, PersonName
, Account
, ParentID
from @Table
; with recursion as
(
select
t1.PersonID
, t1.PersonName
, t1.Account
--, t1.ParentID
, cast(isnull(t2.PersonName, '')
+ Case when t2.PersonName is not null then '\' + t1.PersonName else t1.PersonName end
as varchar(255)) as fullheirarchy
, 1 as pos
, cast(t1.orders +
isnull(t2.orders,0) -- if the parent has no orders than zero
as int) as Orders
from @Table t1
left join @Table t2 on t1.ParentId = t2.PersonId
union all
select
t.PersonID
, t.PersonName
, t.Account
--, t.ParentID
, cast(r.fullheirarchy + '\' + t.PersonName as varchar(255))
, pos + 1 -- increases
, r.orders + t.orders
from @Table t
join recursion r on t.ParentId = r.PersonId
)
, b as
(
select *, max(pos) over(partition by PersonID) as maxrec -- I find the maximum occurrence of position by person
from recursion
)
select *
from b
where pos = maxrec -- finds the furthest down tree
-- and Account = 2 -- I could find just someone from a different department
不确定,但尝试反向加入CTEexample。因此,在p.person\u id=r.father\u id上加入CTEexample c成为在r.person\u id=p.father\u id上加入CTEexample c