Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2008 Forums
 Transact-SQL (2008)
 Recursive CTE, parents and children

Author  Topic 

AK-85
Starting Member

6 Posts

Posted - 2010-04-17 : 12:25:14
Hi everybody,
Can somebody tell me how could I find how many children each parent has? I searched the net but didn't find any example for this.

Thanks!

malpashaa
Constraint Violating Yak Guru

264 Posts

Posted - 2010-04-17 : 13:06:31
You need to specify how you represent the relation parent-child, and to specify what the required query should return(for example is it for the entire tree or for a branch of it).
Go to Top of Page

AK-85
Starting Member

6 Posts

Posted - 2010-04-18 : 09:46:29
Something like if you have a table of people of organization and the have an ID for PK and there is another column which stores the ID of the bosses and that column references to the ID column of the same table. And the point is to get the number of employees under every employee.
Go to Top of Page

malpashaa
Constraint Violating Yak Guru

264 Posts

Posted - 2010-04-18 : 14:05:17
Try this:

IF OBJECT_ID(N'Personnel', 'U') IS NOT NULL
DROP TABLE Personnel;

GO

CREATE TABLE Personnel
(
child_id INT NOT NULL PRIMARY KEY,
parent_id INT REFERENCES Personnel(child_id)
);

INSERT INTO Personnel(child_id, parent_id)
SELECT 1, NULL UNION ALL
SELECT 2, NULL UNION ALL
SELECT 11, 1 UNION ALL
SELECT 12, 1 UNION ALL
SELECT 13, 1 UNION ALL
SELECT 21, 2 UNION ALL
SELECT 22, 2 UNION ALL
SELECT 111, 11 UNION ALL
SELECT 112, 11 UNION ALL
SELECT 121, 12 UNION ALL
SELECT 211, 21 UNION ALL
SELECT 221, 22;

GO

IF OBJECT_ID(N'ufn_GetChilds', 'IF') IS NOT NULL
DROP FUNCTION ufn_GetChilds;

GO

CREATE FUNCTION ufn_GetChilds(@parent_id INT)
RETURNS TABLE AS
RETURN
(
WITH ChildsCTE(child_id, parent_id) AS
(
SELECT child_id, parent_id
FROM Personnel
WHERE parent_id = @parent_id

UNION ALL

SELECT Curr.child_id, Curr.parent_id
FROM ChildsCTE AS Prev
INNER JOIN
Personnel AS Curr
ON Curr.parent_id = Prev.child_id
)
SELECT C.child_id, C.parent_id
FROM ChildsCTE AS C
);

GO

SELECT P.child_id, C.child_count
FROM Personnel AS P
CROSS APPLY
(SELECT COUNT(child_id) AS child_count
FROM ufn_GetChilds(P.child_id) AS C) AS C;
Go to Top of Page

jcelko
Esteemed SQL Purist

547 Posts

Posted - 2010-04-20 : 11:46:19
What you are doing is called the Adjacency List. This poor design choice will require that you write slow, complex recursive code like malpashaa showed you.

Look up the Nested Sets model for hierarchies. Buy a copy of TREES & HIERARCHIES IN SQL. Good DDL leads to easy DML.



--CELKO--
Joe Celko, SQL Guru
Go to Top of Page

Transact Charlie
Master Smack Fu Yak Hacker

3451 Posts

Posted - 2010-04-20 : 12:28:57
quote:
Originally posted by jcelko

What you are doing is called the Adjacency List. This poor design choice will require that you write slow, complex recursive code like malpashaa showed you.

Look up the Nested Sets model for hierarchies. Buy a copy of TREES & HIERARCHIES IN SQL. Good DDL leads to easy DML.

--CELKO--
Joe Celko, SQL Guru


Hi jcelko. May be a little off topic but I'd like to pick your brains, see if I understand the nested set concept:

Say you've got an organisational structure modelled as a nested set. Lets make it simple and say that every person in the hierarchy has exactly two underlings, who have two underlings, who have two underlings..... So the simplest fully populated binary tree.

for the people at the last leaf nodes (those without underlings).

They'd have lft and rgt indices in the middle of the tree range?
(the big boss would be 1 - X)
his underlings are (2 to x/2 - 1) ( (x/2 to X-1)
..
..
Does removing those last leaf people mean that you must update half of the table?

And does inserting new leaf nodes mean you must update the whole table every time? (to adjust all the lft rgt indices).

I can see a lot of the advantages to the nested set model but I'm a little troubled by having to keep track of all the lft rgt dimensions for every insert.

Are there scenarios where you'd not implement nested sets (like very wide trees with a lot of data churn or very shallow trees with lots of leaves and very few branches)?

It's not likely to come up in our shop but I'm interested.

Charlie.


Charlie
===============================================================
Msg 3903, Level 16, State 1, Line 1736
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION
Go to Top of Page
   

- Advertisement -