I need to create MySQL tables that represent a tree structure like this:
Root
|- Chapter 1
| |- Chapter 1.1
| | |- Article 1.1.1
| | |- Article 1.1.2
| |- Article 1.2
| |- Chapter 1.3
| |- Chapter 1.3.1
| | |- Article 1.3.1.1
| | |- Article 1.3.1.2
| |- Article 1.3.2
| |- Article 1.3.3
|- Chapter 2
|-Chapter 2.1
| |- ...
|- Chapter 2.2
|- ...
Simply speaking, there are two types of entity: Chapter and Article. Article is the smallest entity that there is no child under it, while Chapter can contains sub-chapter or articles as children entity. Each entity will have an ID and a Name.
The order of children has no set rule, it can be Chapter, then Article, then Chapter again.
Another challenge is, when a chapter is re-positioned from one chapter to another chapter, all the children should also be re-positioned accordingly. For example, when I move chapter 1.3.1 to under chapter 1.1 (so chapter 1.3.1 becomes chapter 1.1.3), then the article 1.3.1.1 and article 1.3.1.2 should also be moved and become article 1.1.3.1 and article 1.1.3.2. And at the same time Article 1.3.2 and Article 1.3.3 will become Article 1.3.1 and Article 1.3.2 respectively.
So what I’m asking is, how to design the database table so as to present these relationships? And how the SQL will looks like for adding new element / deleting element and re-positioning the elements? (I can use Ajax to handle the re-positioning interaction, and use PHP to generate those hierarchy numbering)
Also, as the tree is generally quite long, I wish to avoid updating of all elements just because only one element is repositioned. (Not sure if this wish is technically possible.)
The best information I have found on representing tree structures in a database is in Joe Celko’s Trees and Hierarchies in SQL for Smarties.
You can probably find enough information on the web but I’d recommend getting the book, I found it very useful when implementing a nested set hierarchy.
You can either use an adjacency list or nested sets to model the tree in the database, I’m assuming you are using an adjacency list (where each entry has a
parentattribute)If you want to be able to move entire sub trees from one parent to anther then it should be as easy as changing the
parent_id(or whatever PK you are using) to reference the new parent. A nested set model requires changes to all the nodes when a sub tree is moved.However, other operations are easier on a nested set, such as selecting all the child nodes under a specific parent. This can be more difficult with the adjacency list model but it has become easier with the advent of recursive CTE.
If you are not worried about the order of the content I would avoid storing the chapter numbers with your data. Apply them when you select the data and then you avoid having to update every node when your tree changes.