I am trying to create a table to manage parent/child relationships for a website. This is not too difficult if it were for one site, however I would like to use this table for multiple sites, as well as subsites.
For example, I have a website ALPHA, a website BETA as well as a Website GAMMA, but the root of website GAMMA is also a page in website ALPHA.
ALPHA | BETA | GAMMA |
---|---|---|
A |-B |-|-C |-|-D |-|-|-E |-|-F |-G |-H |
M |-N |-O |-P |-|-Q |-|-R |
B |-C |-D |-|-E |-F |
As you can see above, site GAMMA’s root of B is also a child of site ALPHA’s A.
This is my schema
IF OBJECT_ID (N'Sites_GetTreeFromPage') IS NOT NULL DROP FUNCTION Sites_GetTreeFromPage GO CREATE FUNCTION dbo.Sites_GetTreeFromPage ( @Page_id uniqueidentifier , @Site_id uniqueidentifier = NULL , @StartDepth int = 0 , @Depth int = NULL ) RETURNS @PageTree TABLE ( Page_id uniqueidentifier PRIMARY KEY NOT NULL , L int NOT NULL , R int NOT NULL , D int NOT NULL , Site_id uniqueidentifier NOT NULL ) AS BEGIN SELECT TOP 1 @Site_id = ISNULL(@Site_id, Site_id) FROM Sites_Pages WHERE Page_id = @Page_id ORDER BY D ASC INSERT INTO @PageTree (Page_id, L, R, D, Site_id) SELECT p.Page_id , tree.L , tree.R , tree.D , s.Site_id FROM Sites_Pages s_p JOIN Sites_Pages tree ON tree.Site_id = s_p.Site_id AND tree.L >= s_p.L AND tree.R <= s_p.R JOIN Pages p ON tree.Page_id = p.Page_id JOIN Sites s ON s_p.Site_id = s.Site_id WHERE s_p.Page_id = @Page_id AND s_p.Site_id = @Site_id AND tree.D >= s_p.D+@startDepth AND (@Depth IS NULL OR tree.D <= s_p.D+@Depth+@startDepth) RETURN END GO
IF OBJECT_ID (N'Sites_GetPageTree') IS NOT NULL DROP PROCEDURE Sites_GetPageTree GO CREATE PROCEDURE Sites_GetPageTree @Page_id uniqueidentifier , @Site_id uniqueidentifier = NULL , @StartDepth int = 0 , @Depth int = NULL AS BEGIN SELECT p.Page_id , p.Title , REPLICATE('| - ', tree.D-@startDepth) + p.Title AS Tree , tree.L , tree.R , tree.D , s.Title AS Site , CASE WHEN tree.L = 1 THEN 1 ELSE 0 END AS IsRoot , CASE WHEN tree.R = tree.L + 1 THEN 1 ELSE 0 END AS IsLeaf , CASE WHEN tree.R > tree.L + 1 THEN 1 ELSE 0 END AS IsParent FROM dbo.Sites_GetTreeFromPage(@Page_id, @Site_id, @StartDepth, @Depth) tree JOIN Pages p ON tree.Page_id = p.Page_id JOIN Sites s ON tree.Site_id = s.Site_id ORDER BY tree.L , tree.R END GO
IF OBJECT_ID (N'Sites_GetPageChildren') IS NOT NULL DROP PROCEDURE Sites_GetPageChildren GO CREATE PROCEDURE Sites_GetPageChildren @Page_id uniqueidentifier AS BEGIN EXEC Sites_GetPageTree @Page_id = @Page_id, @StartDepth = 1, @Depth = 0 END GO
IF OBJECT_ID (N'Sites_GetSiteTree') IS NOT NULL DROP PROCEDURE Sites_GetSiteTree GO CREATE PROCEDURE Sites_GetSiteTree @Site_id uniqueidentifier AS BEGIN DECLARE @Page_id uniqueidentifier SELECT @Page_id = RootPage_id FROM Sites WHERE Site_id = @Site_id EXEC Sites_GetPageTree @Page_id = @Page_id, @Site_id = @Site_id END GO
I am trying to write stored procedures to interact with the Sites_Pages table, but it has been hurting my brain.
The complication is that I would like to perform all operations without having to run different queries for different Sites. Also, I don’t want to use a temporary table to store rows if I want to move Pages from one parent to another.