`
suchj
  • 浏览: 147352 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

better_nested_set——用结构设计代替递归

    博客分类:
  • sql
阅读更多
有如下一棵树:
root
    |_ Child 1
      |_ Child 1.1
      |_ Child 1.2
    |_ Child 2
      |_ Child 2.1
      |_ Child 2.2

也可以写成以下结构:
    ___________________________________________________________________
   |  Root                                                             |
   |    ____________________________    ____________________________   |
   |   |  Child 1                  |   |  Child 2                  |   |
   |   |   __________   _________  |   |   __________   _________  |   |
   |   |  |  C 1.1  |  |  C 1.2 |  |   |  |  C 2.1  |  |  C 2.2 |  |   |
   1   2  3_________4  5________6  7   8  9_________10 11_______12 13  14
   |   |___________________________|   |___________________________|   |
   |___________________________________________________________________|

数字代表左右边界,数据库中表的结构为:
   id | parent_id | lft  | rgt  | data
    1 |           |    1 |   14 | root
    2 |         1 |    2 |    7 | Child 1
    3 |         2 |    3 |    4 | Child 1.1
    4 |         2 |    5 |    6 | Child 1.2
    5 |         1 |    8 |   13 | Child 2
    6 |         5 |    9 |   10 | Child 2.1
    7 |         5 |   11 |   12 | Child 2.2

选出一个父结点parent的所有孩子:
 SELECT * FROM table_name WHERE lft > parent.lft AND lft < parent.rgt

如选出结点Child 1的所有子结点:
 SELECT * FROM table_name WHERE lft > 2 AND lft < 7

结果为:
   id | parent_id | lft  | rgt  | data
    3 |         2 |    3 |    4 | Child 1.1
    4 |         2 |    5 |    6 | Child 1.2

计算一个结点的孩子的数目:
 (right - left - 1)/2

选出node结点和它所有的父结点:
 SELECT * FROM table_name WHERE node.lft BETWEEN lft AND rgt

如选出结点Child 1.2和它所有的父结点:
 SELECT * FROM tabla_name WHERE 5 BETWEEN lft AND rgt

结果为:
   id | parent_id | lft  | rgt  | data
    1 |           |    1 |   14 | root
    2 |         1 |    2 |    7 | Child 1
    4 |         2 |    5 |    6 | Child 1.2

这样比递归查询要快多了。
注意:left和right是数据中的保留字
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics