I have seen it implemented in one table where each row has an ID and then a ParentID field. Here is a script for MSSQL that represents a table I have in a system I support.
Code:
CREATE TABLE [dbo].[BusinessUnitTree](
[ID] [int] IDENTITY(1,1) NOT NULL,
[ParentID] [int] NULL,
[Description] [varchar](100) NOT NULL,
[Active] [bit] NOT NULL,
[EnteredBy] [int] NOT NULL,
[EnteredOn] [datetime] NOT NULL,
[ChangedBy] [int] NULL,
[ChangedOn] [datetime] NULL,
CONSTRAINT [PK_BusinessArea] PRIMARY KEY CLUSTERED
(
[BUID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ) ON [PRIMARY]
A function to build the tree (top down):
Code:
CREATE FUNCTION [dbo].[BusinessUnit_DownTree] (@ID int)
RETURNS @t TABLE(ID int, ParentID int, [Level] int)
AS
BEGIN
WITH cte (BUID, ParentID, BUTypeID, [Level]) AS (
SELECT
ID,
ParentID,
0 as [Level]
FROM
BusinessUnitTree (nolock)
WHERE
ID = @ID
UNION ALL
SELECT
p.ID,
p.ParentID,
cte.[Level] + 1
FROM
cte
JOIN
BusinessUnitTree p (nolock) on p.ParentID = cte.ID
)
INSERT @t
SELECT
ID,
ParentID,
[Level]
FROM cte
RETURN
END
GO