为了账号安全,请及时绑定邮箱和手机立即绑定

SQL - 如何存储和导航层次结构?

/ 猿问

SQL - 如何存储和导航层次结构?

隔江千里 2019-08-16 16:18:43

SQL - 如何存储和导航层次结构?

您在数据库中建模和检索分层信息的方式有哪些?



查看完整描述

3 回答

?
一只甜甜圈

关于这个主题的权威部分是由Joe Celko编写的,他将其中的一些作品编写成了一本名为Joe Celko的树和层次结构的SQL for Smarties。

他赞成一种称为有向图的技术。可在此处找到他关于此主题的工作介绍


查看完整回答
反对 回复 2019-08-16
?
Cats萌萌

我喜欢Modified Preorder Tree Traversal算法。这种技术使查询树变得非常容易。

但是这里有一个关于这个主题的链接列表,我从Zend Framework(PHP)贡献者网页上复制了这个主题(由Laurent Melmoux发布于2007年6月5日15:52)。

许多链接都是语言无关的:

有两种主要的表示和算法来表示具有数据库的层次结构:

  • 嵌套集也称为修改前序树遍历算法

  • 邻接表模型

这里有很好的解释:

以下是我收集的一些链接:

邻接表模型

嵌套集

Graphes

课程:

嵌套集DB树Adodb

访问模型ADOdb

PEAR :: DB_NestedSet

梨树

nstrees


查看完整回答
反对 回复 2019-08-16
?
12345678_0001

在SQL数据库中表示层次结构的最佳方法是什么?一种通用的便携式技术?


我们假设层次结构主要是读取的,但不是完全静态的。让我们说这是一棵家谱。


这是不怎么做:


create table person (

person_id integer autoincrement primary key,

name      varchar(255) not null,

dob       date,

mother    integer,

father    integer

);

并插入如下数据:


person_id   name      dob       mother father  

1           Pops      1900/1/1   null   null  

2           Grandma   1903/2/4   null   null  

3           Dad       1925/4/2   2      1  

4           Uncle Kev 1927/3/3   2      1

5           Cuz Dave  1953/7/8   null   4

6           Billy     1954/8/1   null   3

相反,将节点和关系拆分为两个表。


create table person (

person_id integer autoincrement primary key,

name      varchar(255) not null,

dob       date

);


create table ancestor (

ancestor_id   integer,

descendant_id integer,

distance      integer

);

数据创建如下:


person_id   name      dob       

1           Pops      1900/1/1  

2           Grandma   1903/2/4   

3           Dad       1925/4/2   

4           Uncle Kev 1927/3/3

5           Cuz Dave  1953/7/8   

6           Billy     1954/8/1   


ancestor_id  descendant_id  distance

1            1              0

2            2              0

3            3              0

4            4              0

5            5              0

6            6              0

1            3              1

2            3              1

1            4              1

2            4              1

1            5              2

2            5              2

4            5              1

1            6              2

2            6              2

3            6              1

现在,您可以运行不涉及将表连接回自身的仲裁查询,如果您在与节点相同的行中具有heirachy关系,则会发生这种情况。


谁有祖父母?


select * from person where person_id in 

    (select descendant_id from ancestor where distance=2);

你所有的后代:


select * from person where person_id in 

    (select descendant_id from ancestor 

    where ancestor_id=1 and distance>0);

谁是叔叔?


select decendant_id uncle from ancestor 

    where distance=1 and ancestor_id in 

    (select ancestor_id from ancestor 

        where distance=2 and not exists

        (select ancestor_id from ancestor 

        where distance=1 and ancestor_id=uncle)

    )

您可以避免通过子查询将表连接到自身的所有问题,常见的限制是16个子查询。


麻烦的是,维护祖先表有点难 - 最好用存储过程完成。


查看完整回答
反对 回复 2019-08-16

添加回答

回复

举报

0/150
提交
取消
意见反馈 邀请有奖 帮助中心 APP下载
官方微信