ace25
ace25

Reputation: 33

Database Design: Hierarchical Data

I am having trouble arriving at a normalized relational database design to describe a small hierarchy which deviates enough from the typical hierarchy examples such that I am unsure how to proceed my first time tackling such a problem.

My problem is as follows:

Each branch in the hierarchy is guaranteed to be either 2, 4, or 6 levels deep. If it is 2 levels deep, the hierarchy looks like this:

Category / Group / Component

If it is 4 levels deep, it looks like this:

Category / Group / Component / Group / Component

If it is 6 levels deep, it looks like this:

Category / Group / Component / Group / Component / Group / Component

Categories, Groups, and Components each have their own set of attributes. To further complicate matters, a relationship exists between a Component and entity A, a Component and entity B, and a Component and entity C.

My original thought was to strive to keep the Components in one table, however, I have been unable to come up with a normalized solution that satisfies this goal.

Instead, I came up with a normalized solution where there is a separate table for Components at each of the three possible component levels. However, I am not really comfortable with this because it triples the number of tables capturing links between components and entitites A, B, and C (9 total link tables rather than 3 if all components were in one table).

Here is what the design I came up with looks like:

TABLE: Group_1_Components

ATTRIBUTES: Row_ID, Category, Component

RELATES-TO: Group_1_Components_A_Links, Group_1_Components_B_Links, Group_1_Components_C_Links, Group_2_Components

TABLE: Group_2_Components

ATTRIBUTES: Row_ID, Group, Component, Group_1_Component_Row_ID

RELATES-TO: Group_2_Components_A_Links, Group_2_Components_B_Links, Group_2_Components_C_Links, Group_1_Components, Group_3_Components

TABLE: Group_3_Components

ATTRIBUTES: Row_ID, Group, Component, Group_2_Component_Row_ID

RELATES-TO: Group_3_Components_A_Links, Group_3_Components_B_Links, Group_3_Components_C_Links, Group_2_Components

Each of the 9 links tables contain two Row IDs to address a many-to-many relationship with either table A, B, or C.

Is this a reasonable design or am I overlooking a simpler, more typical solution? I looked at a few design techniques specific to capturing hierarchies in a relational database, notably the adjacency list, but I am not sure they fit here, nor do they appear to be normalized solutions.

It should be noted that the hierarchy will be seldomly modified; it will frequently be read where reads retrieve either all of the components or components at a specific level for a selected group. The link tables to entities A, B, and C will be written to regularly.

Any and all suggestions are welcome. Thanks in advance for your help. Brian

Upvotes: 0

Views: 1483

Answers (2)

ruralcoder
ruralcoder

Reputation: 1020

Another option for this kind of problem is using a self-referencing table. Just one table.

Single table with ID, PARENT_ID and a TYPE so you can distinguish CATEGORY, GROUP and COMPONENT.

All categories would have no PARENT_ID and then you could search for all child objects where the parent id is equal to the id of the category you want to dive deeper into.

Upvotes: 0

Stephen Senkomago Musoke
Stephen Senkomago Musoke

Reputation: 3523

I suggest that you de-normalize your data so that your hierarchy is based on component/group entities, so that you match "regular" hierarchies. In this case you can have the following tables:

a) Components

b) Groups

c) Component_Groups - with a unique key on component_id and group_id to ensure that you only have one combination for each component and group

In this case then your hierarchy will be: Category -> Component_Group -> Component_Group -> Component_Group

Upvotes: 1

Related Questions