Hierarchical Data in MySQL

后端 未结 8 1462
南笙
南笙 2020-12-04 22:57

I\'ve got a sort of tree like thing going on in my MySQL database.

I have a database that has categories, and each category has a subcat. I\'m keeping all the catego

相关标签:
8条回答
  • 2020-12-04 23:58

    I would like to share my idea with you.

    Limitation of Adjacency Model: Follow the Managing Hierarchical Data in MySQL As you already described adjacency model has limitation that you have to know the level before you retrieve path.

    Use Nested model: But if you convert the data structure your data structure to Nested set model then you can still use the self join to get the tree.

    Converting Hierarchical model to Nested model: Now we need a tree travel algorithm to index the nested model. This can be implemented in mysql function (Sorry the conversion needs some algorithm implementation : A tree traversal algorithm. Not sure which one is best fitted).

    Thanks :)

    0 讨论(0)
  • 2020-12-04 23:59

    You want to be given the parent ID:

    So assume you are given

    set @parentId = 1 /*toys*/
    
    select 
      *
    from
      Items i
    inner join Categories c on c.id = i.categoryId
    where
      c.parentId = @parentId
    

    This will give you the items you want - with one major design flaw: it doesn't handle multiple levels of hierarchical categories.

    Let's say you had this Categories table:

    *Categories table*
    id | name    | parentId
    1  | Toys    | 0
    2  | Dolls   | 1
    3  | Bikes   | 1
    4  | Models  | 2
    5  | Act.Fig.| 2
    6  | Mountain| 3
    7  | BMX     | 3
    

    And Items:

    *items table*
    item   | category_id
    Barbie | 4
    GIJoe  | 5
    Schwinn| 6
    Huffy  | 7
    

    The only way to get all the relevant Items is do a self join:

    select 
      *
    from
      Items i 
    inner join Categories c on c.id = i.categoryId
    inner join Categories c2 on c.parentId = c2.id
    where
      c2.parentId = @parentId
    

    This pattern is not scalable - since you can have MULTIPLE levels of hierarchy.

    One common way to deal with hierarchies is to build a "flattened" table: a row that links each node to ALL it's descendants.

    In addition to a Categories table, you build a second table:

    *CategoriesFlat table*  The Name column is here only for readability
    id | name    | parentId
    1  | Toys    | 1
    -----------------
    2  | Dolls   | 1
    2  | Dolls   | 2
    -----------------
    4  | Models  | 1
    4  | Models  | 2
    4  | Models  | 4
    5  | Act.Fig.| 1
    5  | Act.Fig.| 2
    5  | Act.Fig.| 5
    -----------------
    3  | Bikes   | 1
    3  | Bikes   | 3
    -----------------
    6  | Mountain| 1
    6  | Mountain| 3
    6  | Mountain| 6
    7  | BMX     | 1
    7  | BMX     | 3
    7  | BMX     | 7
    

    So you can write:

    select 
      *
    from
      Items i
    inner join CategoriesFlat c on c.id = i.categoryId
    where
      c.parentId = @parentId
    

    And get ALL the relevant Categories and Items.

    Here's a great slideshow about SQL anti-patterns and solutions to them. (Hierarchical data in SQL is an anti-pattern, but don't be disheartened - we all run into this one)

    0 讨论(0)
提交回复
热议问题