Reputation: 1
I have 2 tables. One table contains all parent accounts, top level of hierarchy. Second table has all children accounts, that may or may not have a match to a parent account in the parent table. The goal is to create a query (SQL Server 2008, recursive or non) that finds all child accounts that match to the parent in addition to the fact that the child could itself be a parent to other child accounts.
In simpler terms, once a match has been made on a parent to child, need to check to make sure that the child in the match is not itself a parent to other child accounts. A mouthful I understand and I hope it makes sense. I also do not know the depth of which the hierarchy would extend.
CREATE TABLE dbo.Parent_Accounts
(Parent_Account_Key_Lookup varchar(28) NOT NULL,
Account_Number bigint NOT NULL,
Reference_Account_Number_1 bigint NOT NULL,
Reference_Account_Number_2 bigint NOT NULL,
OpenDate int NOT NULL,
Status char(1) NOT NULL,
Record_Created smalldatetime NOT NULL,
Active bit NOT NULL)
GO
CREATE TABLE dbo.Child_Accounts
(Child_Account_Key_Lookup varchar(28) NOT NULL,
Account_Number bigint NOT NULL,
Reference_Account_Number_1 bigint NOT NULL,
Reference_Account_Number_2 bigint NOT NULL,
OpenDate int NOT NULL,
Status char(1) NOT NULL,
Record_Created smalldatetime NOT NULL,
Active bit NOT NULL)
GO
WITH cte_Recursive
AS (SELECT parent.Account_Number,
parent.Parent_Account_Key_Lookup,
parent.Reference_Account_Number_1,
parent.Reference_Account_Number_2,
parent.OpenDate,
parent.[Status],
parent.Record_Created,
parent.Active,
1 AS Hierarchy_Level
FROM dbo.Parent_Accounts parent
WHERE parent.Account_Number = 4498481055218674
UNION ALL
SELECT child.Account_Number,
child.Child_Account_Key_Lookup,
child.Reference_Account_Number_1,
child.Reference_Account_Number_2,
child.OpenDate,
child.[Status],
child.Record_Created,
child.Active,
cte.Hierarchy_Level + 1
FROM cte_Recursive cte
INNER JOIN dbo.Child_Accounts child
ON cte.Parent_Account_Key_Lookup = child.Child_Account_Key_Lookup)
--SELECT * FROM cte_Recursive
SELECT TOP 2 * FROM cte_Recursive
INSERT INTO dbo.Parent_Accounts
(Parent_Account_Key_Lookup,
Account_Number,
Reference_Account_Number_1,
Reference_Account_Number_2,
OpenDate,
[Status],
Record_Created,
Active)
VALUES ('222248105521867419970702', 2222481055218674, 2222481060975466, 0, 19970702, 'U', '2010-11-18 12:46:00', 0)
INSERT INTO dbo.Child_Accounts
(Child_Account_Key_Lookup,
Account_Number,
Reference_Account_Number_1,
Reference_Account_Number_2,
OpenDate,
[Status],
Record_Created,
Active)
VALUES ('222248105521867419970702', 2222481060975466, 2222481055218674, 2222481055218674, 19970702, 'L', '2010-11-19 08:33:00', 0),
('222248106097546619970702', 2222481060982900, 2222481060989137, 2222481060975466, 19970702, 'U', '2010-11-19 16:54:00', 0),
('222248106098290019970702', 2222481060989137, 0, 2222481060982900, 19970702, ' ', '2010-11-21 01:52:00', 1)
Upvotes: 0
Views: 459
Reputation: 15816
The problem appears to be an inability to specify how to determine that a child has children combined with a lack of identity for children. If the ON
clause in the CTE could prevent a child joining to itself it would break the infinite recursion chain.
Sample output and answers to the comments should make it clear whether you simply need another condition in the ON
clause or a UNION
to handle childrens' children.
This at least stops recursing by limiting the hierarchy level and provides a testbed that anyone can execute without cluttering their database:
declare @Parent_Accounts as table (
Parent_Account_Key_Lookup varchar(28) NOT NULL,
Account_Number bigint NOT NULL,
Reference_Account_Number_1 bigint NOT NULL,
Reference_Account_Number_2 bigint NOT NULL,
OpenDate int NOT NULL,
Status char(1) NOT NULL,
Record_Created smalldatetime NOT NULL,
Active bit NOT NULL)
declare @Child_Accounts as table (
Child_Account_Key_Lookup varchar(28) NOT NULL,
Account_Number bigint NOT NULL,
Reference_Account_Number_1 bigint NOT NULL,
Reference_Account_Number_2 bigint NOT NULL,
OpenDate int NOT NULL,
Status char(1) NOT NULL,
Record_Created smalldatetime NOT NULL,
Active bit NOT NULL)
INSERT INTO @Parent_Accounts
(Parent_Account_Key_Lookup, Account_Number, Reference_Account_Number_1, Reference_Account_Number_2, OpenDate, [Status], Record_Created, Active) VALUES
('222248105521867419970702', 2222481055218674, 2222481060975466, 0, 19970702, 'U', '2010-11-18 12:46:00', 0)
INSERT INTO @Child_Accounts
(Child_Account_Key_Lookup, Account_Number, Reference_Account_Number_1, Reference_Account_Number_2, OpenDate, [Status], Record_Created, Active) VALUES
('222248105521867419970702', 2222481060975466, 2222481055218674, 2222481055218674, 19970702, 'L', '2010-11-19 08:33:00', 0),
('222248106097546619970702', 2222481060982900, 2222481060989137, 2222481060975466, 19970702, 'U', '2010-11-19 16:54:00', 0),
('222248106098290019970702', 2222481060989137, 0, 2222481060982900, 19970702, ' ', '2010-11-21 01:52:00', 1)
; WITH cte_Recursive
AS (SELECT parent.Account_Number,
parent.Parent_Account_Key_Lookup,
parent.Reference_Account_Number_1,
parent.Reference_Account_Number_2,
parent.OpenDate,
parent.[Status],
parent.Record_Created,
parent.Active,
1 AS Hierarchy_Level
FROM @Parent_Accounts parent
WHERE parent.Account_Number = 2222481055218674
UNION ALL
SELECT child.Account_Number,
child.Child_Account_Key_Lookup,
child.Reference_Account_Number_1,
child.Reference_Account_Number_2,
child.OpenDate,
child.[Status],
child.Record_Created,
child.Active,
cte.Hierarchy_Level + 1
FROM cte_Recursive cte
INNER JOIN @Child_Accounts child
ON cte.Parent_Account_Key_Lookup = child.Child_Account_Key_Lookup and cte.Hierarchy_Level < 2)
SELECT * FROM cte_Recursive
Upvotes: 0