I need to retrieve the list of full paths of groups (folders) stored in the database as such:
select * from groups;
group_id parent_group_id name
-------- --------------- -------------------------------
1 NULL Root
2 1 Folder1
3 2 Folder2
4 3 Folder3
There is no limit to the possible depth of groups (could be nested almost indefinitely), so I don't know in advance how many levels I could have.
I would like to be able to get the following results from a query and load that into a table that I could use to join full paths with group_ids in other queries:
group_id path
-------- --------------------------------------------
1 /Root
2 /Root/Folder1
3 /Root/Folder1/Folder2
4 /Root/Folder1/Folder2/Folder3
I've been looking at some other examples with similar needs, but it never seems to fit perfectly to what I want, and without a clear example, I'm having trouble to do it alone.
The only thing I could think of was to join aliases of the same table up to the max number of levels, which could be a lot, and that is not practical. I would need a way to loop recursively somehow for each group and go up the tree, appending the path to a variable until I'm at the end, and then store the deepest child ID and its full path in a table.
Performance is also very important. This is a production database and I can't afford slowdowns, which is why I want to dump it only when I need it and then reuse static data. Ultimately I want to dump thousands of records each linking to a group_id and print their full path.
Without giving me the whole thing for free, could someone point me in the right direction and maybe give me a generic example to copy from?
We are using SQL Server 2008 R2.
Sounds like something that using a recursive CTE might be able to solve. A CTE (or common table expression) will allow you to create a table-like structure without having to create a table or view. CTEs also allow you to create recursive queries, which in your case can help tremendously. The structure allows you to join the CTE onto itself, lending to a 'cascading' type of result as you're intending to achieve here.
For example, you could do something like this:
WITH grouppaths (group_id, group_path) AS
(
SELECT group_id, pathname
FROM GroupPath
WHERE parent_group_id IS NULL
UNION ALL
SELECT gp.group_id, gps.group_path + '/' + gp.pathname
FROM GroupPath gp
JOIN grouppaths gps ON gps.group_id = gp.parent_group_id
)
SELECT
group_id, group_path
FROM
grouppaths
You can check this out here using SqlFiddle.
Microsoft provides information and samples about using CTEs here: http://msdn.microsoft.com/en-us/library/ms190766%28v=sql.105%29.aspx
More specifically, this link provides further information about recursive CTEs: http://msdn.microsoft.com/en-us/library/ms186243%28v=sql.105%29.aspx