Reputation: 7
I am trying to read from Sql a virtual file system structure. I would like to be able to use the child/parent recurse, but then be able to change a folder name and then all children from the old folder name show the new folder name.
--Create temporary table
CREATE TABLE #Objects (
child VARCHAR(20),
parent VARCHAR(20),
ObjectType int
)
--Insert some rows
INSERT INTO #Objects (child,parent,ObjectType) VALUES ('Folder1',NULL,1)
INSERT INTO #Objects (child,parent,ObjectType) VALUES ('File1','Folder1',0)
INSERT INTO #Objects (child,parent,ObjectType) VALUES ('File2','Folder1',0)
INSERT INTO #Objects (child,parent,ObjectType) VALUES ('Folder2','Folder1',1) -- Folder1 gets renamed to Folder2
INSERT INTO #Objects (child,parent,ObjectType) VALUES ('File3','Folder2',0)
--Try to recurse
;WITH cteLevelOne (parent, child, Depth) AS
(
SELECT a.parent, a.child, 1 as Depth
FROM #Objects AS a
WHERE ObjectType = 1 -- Folder
AND Parent IS NULL
UNION ALL
SELECT a.parent, a.child, c.Depth + 1 as Depth
FROM #Objects AS a
INNER JOIN cteLevelOne AS c ON a.child = c.parent
WHERE ObjectType = 0 -- File
)
select * from CTELevelone
Output received
parent child Depth
NULL Folder1 1
required output (files and their current folder)
--Folder2 File1
--Folder2 File2
--Folder2 File3
Can anyone help?
Upvotes: 0
Views: 96
Reputation: 9274
If i understood you correctly, you want something like this:
CREATE TABLE #Objects (
child VARCHAR(20),
parent VARCHAR(20),
ObjectType int
)
INSERT INTO #Objects (child,parent,ObjectType)
VALUES ('Folder1',NULL,1)
,('File1','Folder1',0)
,('File2','Folder1',0)
,('Folder2','Folder1',1) -- Folder1 gets renamed to Folder2
,('File3','Folder2',0)
,('Folder3','Folder2',1)
,('File4','Folder3',0)
,('Folder4',NULL,1)
,('Folder5',NULL,1)
,('Folder6','Folder5',1)
,('File5','Folder5',0)
,('File6','Folder6',0)
;WITH cte AS (
SELECT child AS path, child AS parent
, 1 AS level
FROM #objects so
WHERE parent IS NULL
AND ObjectType = 1
UNION ALL
SELECT c.path, o.child
, level + 1
FROM cte c
INNER JOIN #Objects o
ON o.parent = c.parent
AND ObjectType = 1
)
SELECT o.child, latest.parent as filePath
FROM #Objects o
INNER JOIN cte c -- Get the real parent
ON c.parent = o.parent
CROSS apply ( -- Get the most recent level for the path
SELECT TOP 1 parent
FROM cte c2
WHERE c2.path = c.path
ORDER BY level DESC
) latest
WHERE o.ObjectType = 0
I create a cte which builds a original root folder for each path. Then for each file, one can go through the parent folder back to original root folder, and finally get the most recent folder name for the original root.
Upvotes: 0
Reputation: 49395
I don't have a 2008 r2 any more for some years, but i would repace first the names and then make the recursive CTE
WITH First_rename as (
SELECT child, Parent FROM #Objects
WHERE ObjectType = 1 -- Folder
AND Parent IS NOT NULL),
replace_folder as (
SELECT COALESCE(f1.child,o.child) [child],COALESCE(f.child,o.parent) [parent],ObjectType
fROM #Objects o LEFT JOIN First_rename f ON o.parent = f.parent
LEFT JOIN First_rename f1 ON o.child = f1.parent
)
,
cteLevelOne (parent, child, Depth) as
(
SELECT a.parent, a.child, 1 as Depth
FROM replace_folder AS a
WHERE ObjectType = 1 -- Folder
AND Parent IS NULL
UNION ALL
SELECT a.parent, a.child, c.Depth + 1 as Depth
FROM replace_folder AS a
INNER JOIN cteLevelOne AS c ON c.child = a.parent
WHERE ObjectType = 0 -- File
)
select * from CTELevelone WHERE Parent is NOT NULL
parent | child | Depth |
---|---|---|
Folder2 | File1 | 2 |
Folder2 | File2 | 2 |
Folder2 | File3 | 2 |
Upvotes: 0