Dump list of full paths of parent/child type records in SQL Server 2008 R2

天涯浪子 提交于 2019-12-12 10:09:56

问题


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.


回答1:


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




回答2:


Based on the link posted by Matt Johnson, I was able to solve my challenge as such:

WITH group_paths (group_id, group_path)
AS
(
-- Anchor member definition
    SELECT g.group_id, cast('/'+g.name as varchar(max)) as group_path
    FROM dbo.blgroup AS g
    WHERE parent_group_id=0
    UNION ALL
-- Recursive member definition
    SELECT g.group_id, cast(group_path + '/' + g.name as varchar(max))
    FROM dbo.blgroup AS g
    INNER JOIN group_paths AS gp
        ON g.parent_group_id = gp.group_id
)
-- Statement that executes the CTE
SELECT group_id, group_path
FROM group_paths

The result looks like this, which is exactly what I needed:

group_id    group_path
----------- ----------------------------------------
1000001     /Servers
1000002     /Depot
1000003     /Jobs
1000004     /Component Templates
1000006     /System Packages
1000005     /Components
1000008     /Patch Repository
1000007     /Device
1000010     /Device/Imported
1000011     /Device/Provisioned
1000009     /Patch Repository/Patches By Subscription
2000148     /Components/Customers


来源:https://stackoverflow.com/questions/15282938/dump-list-of-full-paths-of-parent-child-type-records-in-sql-server-2008-r2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!