假设我有以下架构:
person (person_id, person_account, name)
relationships (person_id, father_id)
purchases(person_account, total, type)
免责声明:我没有设计这个架构,我知道这很糟糕所以我道歉。这也是一个例子,这要复杂得多。另请注意,这是我将在JDBCTemplate中使用的查询,这就是我添加标记的原因。
现在我想得到一个人的count
购买,他或她的儿子购买和他们的儿子购买等等。我想在初始人身上找到一个特定的起点。
与我迄今为止看到的例子有所不同:
person_account
)。purchases
没有person_id
字段,因此使事情变得复杂。count
而不是其他东西。type
的{{1}}进行过滤。purchase
关系在另一个表中,因此意味着必须进行连接。再次它很可怕但我无法更改数据库以在father_id
表中包含father_id
字段。person
表中没有条目。这将使情况进一步复杂化。现在我已经阅读了这些例子,我理解了其中几个:
How to get all children of a parent and then their children using recursion in query
SQL Server recursive query
http://msdn.microsoft.com/en-us/library/ms186243.aspx
但是,我在理解起点和终点时遇到了问题。我的起点COULD有一个父亲,因此不能为空。我的端点应该从relationships
表上没有条目的人那里获得purchases
。
所以我在想的是:
relationships
然而,它根本不起作用。
任何帮助都将不胜感激。
答案 0 :(得分:2)
你有一个非常详细的问题,但我的猜测是你在递归CTE中的谓词造成了严重破坏。通常,您需要通过递归和搜索树来完成两件重要的事情:
以下是可能适用于您的示例:
递归的好处不是一个或两个级别,而是当你达到5级或更多级别并且有能力告诉表达式你想要它的哪一部分。我通常在做递归时做2个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
答案 1 :(得分:1)
保持递归简单(其他人更容易管理)并使用它来获取关系。从那里,您可以加入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