怎么将数据库中存的树转化为树形列表(数据库如何存储树形结构)

怎么将数据库中存的树转化为树形列表(数据库如何存储树形结构),第1张

先从数据结构的角度来答

题主应该知道B-树和B树最重要的一个区别就是B树只有叶节点存放数据,其余节点用来索引,而B-树是每个索引节点都会有Data域

这就决定了B树更适合用来存储外部数据,也就是所谓的磁盘数据

从Mysql(Inoodb)的角度来看,B树是用来充当索引的,一般来说索引非常大,尤其是关系性数据库这种数据量大的索引能达到亿级别,所以为了减少内存的占用,索引也会被存储在磁盘上

那么Mysql如何衡量查询效率呢?磁盘IO次数,B-树(B类树)的特定就是每层节点数目非常多,层数很少,目的就是为了就少磁盘IO次数,当查询数据的时候,最好的情况就是很快找到目标索引,然后读取数据,使用B树就能很好的完成这个目的,但是B-树的每个节点都有data域(指针),这无疑增大了节点大小,说白了增加了磁盘IO次数(磁盘IO一次读出的数据量大小是固定的,单个数据变大,每次读出的就少,IO次数增多,一次IO多耗时啊!),而B树除了叶子节点其它节点并不存储数据,节点小,磁盘IO次数就少

这是优点之一

另一个优点是什么,B树所有的Data域在叶子节点,一般来说都会进行一个优化,就是将所有的叶子节点用指针串起来

这样遍历叶子节点就能获得全部数据,这样就能进行区间访问啦

至于MongoDB为什么使用B-树而不是B树,可以从它的设计角度来考虑,它并不是传统的关系性数据库,而是以Json格式作为存储的nosql,目的就是高性能,高可用,易扩展

首先它摆脱了关系模型,上面所述的优点2需求就没那么强烈了,其次Mysql由于使用B树,数据都在叶节点上,每次查询都需要访问到叶节点,而MongoDB使用B-树,所有节点都有Data域,只要找到指定索引就可以进行访问,无疑单次查询平均快于Mysql(但侧面来看Mysql至少平均查询耗时差不多)

总体来说,Mysql选用B树和MongoDB选用B-树还是以自己的需求来选择的

1、用代码在treeview web控件中,添加node的方法 表字段:编号,父编号,名称 数据: 1 0 中华人民共和国 2 1 湖南 3 1 湖北 void creattree(string text,TreeNode tnd,string pid) { TreeNode t2=new TreeNode(); t2Text=text; tndNodesAdd(t2); 生成 string str1 ="父编号 = '"+pid+"'"; DataRow[] dryl = dataSet31Tables [0]Select(str1); for(int i=0;i<=drylGetUpperBound(0);i++) { creattree(dryl[2]ToString(),t2,dryl[0]ToString()); } } // TreeNode t1=new TreeNode(); t1Text="地区信息"; TreeView2NodesAdd(t1); creattree("中华人民共和国",t1,"1"); 2、如何为TreeView添加事件? Private Sub TreeView1_indexChanged(ByVal sender As Object, ByVal e As MicrosoftWebUIWebControlsTreeViewSelectEventArgs) Handles TreeView1SelectedIndexChange Dim a As Integer a = TreeView1SelectedNodeIndex TextBox1Text = CStr(a) End Sub 但是AutoPostBack设置为True的话,TreeView还要刷新,闪烁,我的TreeView比较庞大 ,这可怎么办???苦恼中。。。 3、为什么TreeView 中的SelectedIndexChange为什么不执行??? AutoPostBack属性为真,SelectedIndexChange才能被执行。 不过这样的话你选择时会感到刷新得让你痛苦,根据你的具体实现的目的,采用变通的 方法,尽量不使用SelectedIndexChange事件吧。 selectedindexchange事件挂到控件上没有? InitializeComponent方法中检查检查 4、如何判断 TreeView 的一个节点下是否有子节点??? if(selNodeNodesCount==0){ //该节点没有字节点 } 5、如何得到 TreeView 的当前选择节点??? 1TreeGetNodeFromIndex(TreeSelectedNodeIndexToString()) 2private void TreeView1_SelectedIndexChange(object sender, MicrosoftWebUIWebControlsTreeViewSelectEventArgs e) eNewNode即为所选节点 6、treeview实现两层节点没问题,扩展到无限层就出问题了? 我的那个做法还不够完善,对于节点数较少的情况可以这样做,对于节点数较多的情况 ,你就不能这样做了,你应该只加载一级,当点击节点展开时,再加载它的下一级子节 点。 数据库结构如下: 表名:Table1 ParentID varchar 20:父节点 ID varchar 20:节点 Name varchar 50:名称 来来来,这里给你个例程,再给个我的网页上的TreeViwe看看,一万个子节点都没问题 。 >

树状结构的数据保存在数据库中的常用方法有一下两种:

1、邻接表(adjacency list model)

2、预排序遍历树算法(modified preorder tree traversal algorithm)

用一下的例子讨论这两种方法的差异:

现有一棵树如下:

邻接表模式:

这种模式我们经常用到,很多的教程和书中也介绍过。我们通过给每个节点增加一个属性 parent 来表示这个节点的父节点从而将整个树状结构通过平面的表描述出来。根据这个原则,例子中的数据可以转化成如下的表:

我们看到 Pear 是Green的一个子节点,Green是Fruit的一个子节点。而根节点'Food'没有父节点。 为了简单地描述这个问题, 这个例子中只用了name来表示一个记录。 在实际的数据库中,你需要用数字的id来标示每个节点,数据库的表结构大概应该像这样:id, parent_id, name, description。

以下是代码:

<php

// $parent is the parent of the children we want to see

// $level is increased when we go deeper into the tree,

// used to display a nice indented tree

function display_children($parent, $level)

{

// 获得一个 父节点 $parent 的所有子节点

$result = mysql_query('SELECT name FROM tree '

'WHERE parent="'$parent'";');

// 显示每个子节点

while ($row = mysql_fetch_array($result))

{

// 缩进显示节点名称

echo str_repeat(' ',$level)$row['name']"n";

//再次调用这个函数显示子节点的子节点

display_children($row['name'], $level+1);

}

}

>

对整个结构的根节点(Food)使用这个函数就可以打印出整个多级树结构,由于Food是根节点它的父节点是空的,所以这样调用: display_children('',0)。将显示整个树的内容:

Food

Fruit

Red

Cherry

Yellow

Banana

Meat

Beef

Pork

如果你只想显示整个结构中的一部分,比如说水果部分,就可以这样调用:display_children('Fruit',0);

几乎使用同样的方法我们可以知道从根节点到任意节点的路径。比如 Cherry 的路径是 "Food >; Fruit >; Red"。 为了得到这样的一个路径我们需要从最深的一级"Cherry"开始, 查询得到它的父节点"Red"把它添加到路径中, 然后我们再查询Red的父节点并把它也添加到路径中,以此类推直到最高层的"Food"

以下是代码:

<php

// $node 是那个最深的节点

function get_path($node)

{

// 查询这个节点的父节点

$result = mysql_query('SELECT parent FROM tree '

'WHERE name="'$node'";');

$row = mysql_fetch_array($result);

// 用一个数组保存路径

$path = array();

// 如果不是根节点则继续向上查询

// (根节点没有父节点)

if ($row['parent']!='')

{

// the last part of the path to $node, is the name

// of the parent of $node

$path[] = $row['parent'];

// we should add the path to the parent of this node

// to the path

$path = array_merge(get_path($row['parent']), $path);

}

// return the path

return $path;

}

>

如果对"Cherry"使用这个函数:print_r(get_path('Cherry')),就会得到这样的一个数组了:

Array

(

[0] =>; Food

[1] =>; Fruit

[2] =>; Red

)

接下来如何把它打印成你希望的格式,就是你的事情了。

缺点:

这种方法很简单,容易理解,好上手。但是也有一些缺点。主要是因为运行速度很慢,由于得到每个节点都需要进行数据库查询,数据量大的时候要进行很多查询才能完成一个树。另外由于要进行递归运算,递归的每一级都需要占用一些内存所以在空间利用上效率也比较低。

预排序遍历树算法

现在让我们看一看另外一种不使用递归计算,更加快速的方法,这就是预排序遍历树算法(modified preorder tree traversal algorithm) 这种方法大家可能接触的比较少,初次使用也不像上面的方法容易理解,但是由于这种方法不使用递归查询算法,有更高的查询效率。

我们首先将多级数据按照下面的方式画在纸上,在根节点Food的左侧写上 1 然后沿着这个树继续向下 在 Fruit 的左侧写上 2 然后继续前进,沿着整个树的边缘给每一个节点都标上左侧和右侧的数字。最后一个数字是标在Food 右侧的 18。 在下面的这张图中你可以看到整个标好了数字的多级结构。(没有看懂?用你的手指指着数字从1数到18就明白怎么回事了。还不明白,再数一遍,注意移动你的手指)。

这些数字标明了各个节点之间的关系,"Red"的号是3和6,它是 "Food" 1-18 的子孙节点。 同样,我们可以看到 所有左值大于2和右值小于11的节点 都是"Fruit" 2-11 的子孙节点

这样整个树状结构可以通过左右值来存储到数据库中。继续之前,我们看一看下面整理过的数据表。

注意:由于"left"和"right"在 SQL中有特殊的意义,所以我们需要用"lft"和"rgt"来表示左右字段。 另外这种结构中不再需要"parent"字段来表示树状结构。也就是 说下面这样的表结构就足够了。

SELECT FROM tree WHERE lft BETWEEN 2 AND 11;

看到了吧,只要一个查询就可以得到所有这些节点。为了能够像上面的递归函数那样显示整个树状结构,我们还需要对这样的查询进行排序。用节点的左值进行排序:

SELECT FROM tree WHERE lft BETWEEN 2 AND 11 ORDER BY lft ASC;

jsp从mysql数据库读取数据,并填充到树形结构菜单并展现出来的实现方法:

1、引入jquerytreeviewjs树控件

<script type="text/javascript" src="jquery/easyui/jqueryminjs"></script>

<script type="text/javascript" src="jquery/easyui/jqueryeasyuiminjs"></script>

2、jsp页面中获取后台mysql数据,并传到jsp页面来

<%

// 数据库的名字

String dbName = "zap";

// 登录数据库的用户名

String username = "sa";

// 登录数据库的密码

String password = "123";

// 数据库的IP地址,本机可以用 localhost 或者 127001

String host = "127001";

// 数据库的端口,一般不会修改,默认为1433

int port = 1433;

String connectionUrl = "jdbc:sqlserver://" + host + ":" + port + ";databaseName=" + dbName + ";user=" + username

+ ";password=" + password;

//

//声明需要使用的资源

// 数据库连接,记得用完了一定要关闭

Connection con = null;

// Statement 记得用完了一定要关闭

Statement stmt = null;

// 结果集,记得用完了一定要关闭

ResultSet rs = null;

try {

// 注册驱动

ClassforName("commicrosoftsqlserverjdbcSQLServerDriver");

// 获得一个数据库连接

con = DriverManagergetConnection(connectionUrl);

String SQL = "SELECT from note";

// 创建查询

stmt = concreateStatement();

// 执行查询,拿到结果集

rs = stmtexecuteQuery(SQL);

while (rsnext()) {

%>

<tr>

3、填充树形菜单:

{

id : "string" // will be autogenerated if omitted

text : "string" // node text

icon : "string" // string for custom

state : {

opened : boolean // is the node open

disabled : boolean // is the node disabled

selected : boolean // is the node selected

},

children : [] // array of strings or objects

li_attr : {} // attributes for the generated LI node

a_attr : {} // attributes for the generated A node

}

$('#tree')jstree({

'core' : {

'data' : function (obj, cb) {

cbcall(this,

['Root 1', 'Root 2']);

}

}});

先根据父编码排序,父编码相同的情况下再根据子编码排序

SELECT id,name

FROM [Table1]

ORDER BY ISNULL(sjbm,0)+'',id

不确定你的sjbm是什么类型的,假如是int型的话,就要判断为NULL值的情况,对你给的数据分析,顶级数据的sjbm值可能是空的

产生的结果应该是

1 a

2 b 1

4 d 1

3 c 2

5 e 4

6 f 4

但是这样只能实现二级项排序,对于你现有的数据,应该是3级项,可以实现,但如果是N级项的话,就只能在存储过程里实现了

以下是3级项排序的实现方法,其中的排序值就是各项Id,以“”分隔:

--1级项,sjbm为空,排序值为(x)

SELECT id,name ,id orderId

FROM [Table1]

WHERE sjbm IS NULL

union all

--2级项,sjbm与1级项的id相等,排序值为(xy)

SELECT id,name ,[lv1]id + '' + [lv2]id

FROM [Table1] AS [lv2]

INNER JOIN

(

SELECT id

FROM [Table1]

WHERE sjbm IS NULL

) AS [lv1] ON [lv2]sjbm = [lv1]id

UNION ALL

--3级项,sjbm与2级项的id相等,排序值为(xyz)

SELECT id,name ,[lv2]sjbm + '' + [lv2]id + '' + [lv3]id

FROM [Table1] AS [lv3]

INNER JOIN

(

SELECT id,name,sjbm

FROM [Table1]

WHERE sjbm IN

(

SELECT id

FROM [Table1]

WHERE sjbm IS NULL

) AS [lv2] ON [lv3]sjbm=[lv2]id

ORDER BY orderId

如果显示OrderId的话,应该如下结果

1 a 1

2 b 12

3 c 123

4 d 14

5 e 145

6 f 146

以上就是关于怎么将数据库中存的树转化为树形列表(数据库如何存储树形结构)全部的内容,包括:怎么将数据库中存的树转化为树形列表(数据库如何存储树形结构)、.net怎么连接sql数据库创建树结构、怎么将数据库中存的树转化为树形列表等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/9358618.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-27
下一篇 2023-04-27

发表评论

登录后才能评论

评论列表(0条)

保存