資料庫樹
Ⅰ 請教如何用資料庫保存樹形結構的數據
在表裡建立兩個欄位,一個是本記錄ID,一個是本記錄所對應的父節點的信息所在的ID,如下:
id
int,
parentid
int,
....
解決方法很多!數據要存儲為樹形結構,那麼數據要有父子關系。
一個父節點有多個子節點,一個子節點又有多個子子節點。
publicclassTreeNode{
/**節點主鍵**/
privateStringid;
/**節點名稱**/
privateStringtext;
/**子節點**/
privateTreeNode[]children;
}
Ⅲ jsp怎麼從mysql資料庫把樹形結構展現出來
jsp從mysql資料庫讀取數據,並填充到樹形結構菜單並展現出來的實現方法:
1、引入jquery.treeview.js樹控制項
<script type="text/javascript" src="jquery/easyui/jquery.min.js"></script>
<script type="text/javascript" src="jquery/easyui/jquery.easyui.min.js"></script>
2、jsp頁面中獲取後台mysql數據,並傳到jsp頁面來
<%
// 資料庫的名字
String dbName = "zap";
// 登錄資料庫的用戶名
String username = "sa";
// 登錄資料庫的密碼
String password = "123";
// 資料庫的IP地址,本機可以用 localhost 或者 127.0.0.1
String host = "127.0.0.1";
// 資料庫的埠,一般不會修改,默認為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 {
// 注冊驅動
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
// 獲得一個資料庫連接
con = DriverManager.getConnection(connectionUrl);
String SQL = "SELECT * from note";
// 創建查詢
stmt = con.createStatement();
// 執行查詢,拿到結果集
rs = stmt.executeQuery(SQL);
while (rs.next()) {
%>
<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) {
cb.call(this,
['Root 1', 'Root 2']);
}
}});
Ⅳ java 遞歸資料庫生成 樹形結構問題
1、准備表結構及對應的表數據
a、表結構:
create table TB_TREE
(
CID NUMBER not null,
CNAME VARCHAR2(50),
PID NUMBER //父節點
)
b、表數據:
insert into tb_tree (CID, CNAME, PID) values (1, '中國', 0);
insert into tb_tree (CID, CNAME, PID) values (2, '北京市', 1);
insert into tb_tree (CID, CNAME, PID) values (3, '廣東省', 1);
insert into tb_tree (CID, CNAME, PID) values (4, '上海市', 1);
insert into tb_tree (CID, CNAME, PID) values (5, '廣州市', 3);
insert into tb_tree (CID, CNAME, PID) values (6, '深圳市', 3);
insert into tb_tree (CID, CNAME, PID) values (7, '海珠區', 5);
insert into tb_tree (CID, CNAME, PID) values (8, '天河區', 5);
insert into tb_tree (CID, CNAME, PID) values (9, '福田區', 6);
insert into tb_tree (CID, CNAME, PID) values (10, '南山區', 6);
insert into tb_tree (CID, CNAME, PID) values (11, '密雲縣', 2);
insert into tb_tree (CID, CNAME, PID) values (12, '浦東', 4);
2、TreeNode對象,對應tb_tree
public class TreeNode implements Serializable {
private Integer cid;
private String cname;
private Integer pid;
private List nodes = new ArrayList();
public TreeNode() {
}
//getter、setter省略
}
3、測試數據
public class TreeNodeTest {
@Test
public void loadTree() throws Exception{
System.out.println(JsonUtils.javaToJson(recursiveTree(1)));
}
/**
* 遞歸演算法解析成樹形結構
*
* @param cid
* @return
* @author jiqinlin
*/
public TreeNode recursiveTree(int cid) {
//根據cid獲取節點對象(SELECT * FROM tb_tree t WHERE t.cid=?)
TreeNode node = personService.getreeNode(cid);
//查詢cid下的所有子節點(SELECT * FROM tb_tree t WHERE t.pid=?)
List childTreeNodes = personService.queryTreeNode(cid);
//遍歷子節點
for(TreeNode child : childTreeNodes){
TreeNode n = recursiveTree(child.getCid()); //遞歸
node.getNodes().add(n);
}
return node;
}
}
輸出的json格式如下:
{
"cid": 1,
"nodes": [
{
"cid": 2,
"nodes": [
{
"cid": 11,
"nodes": [
],
"cname": "密雲縣",
"pid": 2
}
],
"cname": "北京市",
"pid": 1
},
{
"cid": 3,
"nodes": [
{
"cid": 5,
"nodes": [
{
"cid": 7,
"nodes": [
],
"cname": "海珠區",
"pid": 5
},
{
"cid": 8,
"nodes": [
],
"cname": "天河區",
"pid": 5
}
],
"cname": "廣州市",
"pid": 3
},
{
"cid": 6,
"nodes": [
{
"cid": 9,
"nodes": [
],
"cname": "福田區",
"pid": 6
},
{
"cid": 10,
"nodes": [
],
"cname": "南山區",
"pid": 6
}
],
"cname": "深圳市",
"pid": 3
}
],
"cname": "廣東省",
"pid": 1
},
{
"cid": 4,
"nodes": [
{
"cid": 12,
"nodes": [
],
"cname": "浦東",
"pid": 4
}
],
"cname": "上海市",
"pid": 1
}
],
"cname": "中國",
"pid": 0
}
Ⅳ 資料庫中如何實現對樹形結構的存儲
用遞歸或外部程序組織循環,具體跟你的資料庫表結構有關
Ⅵ oracle資料庫,樹形結構維護,添加欄位值
為什麼這樣設計?我認為是設計上不太好。問題的本質是勞動街的爸爸是南崗區,南崗區的爸爸是哈爾濱,哈爾濱的爸爸是黑龍江,這個問題的實質是找到最上層的節點。
建議你首先學習一下Oralce獨有的ConnectBy查詢。特別是level什麼的虛擬欄位要搞懂。
table結構修改成:地區代碼 父地區代碼 地區名稱 足夠了
然後通過connect by 地區代碼=父代碼 找到root的這個記錄的地區名字,問題解決
現在這個結構,假設不找黑龍江,要找到哈爾濱,得了,要吐血了。
===追加一下,假設表已經有了,可以通過視圖修改成父,子結構。用字元函數截取,得到父地區的郵編,同樣也能解決問題。這樣做性能不好,會大量的全表掃描。性能的根本果然在於設計。
Ⅶ 樹形資料庫有哪些
樹形資料庫介紹與特徵:
關系資料庫中BOM結構是樹狀的,但是速度不怎麼樣。
理想中樹形結構應該具備如下特徵:
數據存儲冗餘度小、直觀性強;
檢索遍歷過程簡單高效;
節點增刪改查CRUD操作高效。
Ⅷ 如何設計資料庫樹狀數據結構
然後我覺得首先不要太關注裡面數據結構用C語言的實現方法。第一步,先把書看一遍,省略裡面C語言的具體描述,也就是先不看這些。也不要看那些計算公式,只需要弄清楚裡面的概念,比如說線性表,首先只需要弄清楚什麼是線性表,最好能給自己列個大綱,比如,線性結構-樹狀結構-圖狀結構,然後在細分,把所有的概念全部看懂。第二步,看第二遍書的時候,在去仔細看那些結構的定義語句,以及每種結構有哪些基本演算法,以及是怎樣用C語言來實現的。第三步,最後再去看一些公式,比如時間復雜度,等等。當然,這個是需要有高等數學的根基的。第四步,盡量用自己掌握的一些數據結構來用C語言描述,找些實例來做做,也就是實踐一下。最後如果還有興趣的話可以再深一層的去看看一些軟體工程里的一些基本演算法。相信你會學好數據結構的~
Ⅸ 怎麼將資料庫中存的樹轉化為樹形列表
樹狀結構的數據保存在資料庫中的常用方法有一下兩種:
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;
那麼某個節點到底有多少子孫節點呢?很簡單,子孫總數=(右值-左值-1)/2
descendants = (right – left - 1) / 2 ,如果不是很清楚這個公式,那就去翻下書,我們在上數據結構寫的很清楚!
添加同一層次的節點的方法如下:
LOCK TABLE nested_category WRITE;
SELECT @myRight := rgt FROM nested_category WHERE name = 'Cherry';
UPDATE nested_category SET rgt = rgt + 2 WHERE rgt > @myRight;
UPDATE nested_category SET lft = lft + 2 WHERE lft > @myRight;
INSERT INTO nested_category(name, lft, rgt) VALUES('Strawberry', @myRight + 1, @myRight + 2);
UNLOCK TABLES;
添加樹的子節點的方法如下:
LOCK TABLE nested_category WRITE;
SELECT @myLeft := lft FROM nested_category WHERE name = 'Beef';
UPDATE nested_category SET rgt = rgt + 2 WHERE rgt > @myLeft;
UPDATE nested_category SET lft = lft + 2 WHERE lft > @myLeft;
INSERT INTO nested_category(name, lft, rgt) VALUES('charqui', @myLeft + 1, @myLeft + 2);
UNLOCK TABLES;
每次插入節點之後都可以用以下SQL進行查看驗證:
SELECT CONCAT( REPEAT( ' ', (COUNT(parent.name) - 1) ), node.name) AS name
FROM nested_category AS node,
nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
GROUP BY node.name
ORDER BY node.lft;
刪除節點的方法,稍微有點麻煩是有個中間變數,如下:
LOCK TABLE nested_category WRITE;
SELECT @myLeft := lft, @myRight := rgt, @myWidth := rgt - lft + 1
FROM nested_category WHERE name = 'Cherry';
DELETE FROM nested_category WHERE lft BETWEEN @myLeft AND @myRight;
UPDATE nested_category SET rgt = rgt - @myWidth WHERE rgt > @myRight;
UPDATE nested_category SET lft = lft - @myWidth WHERE lft > @myRight;
UNLOCK TABLES;
這種方式就是有點難的理解,但是適合數據量很大規模使用,查看所有的結構只需要兩條SQL語句就可以了,在添加節點和刪除節點的時候略顯麻煩,不過相對於效率來說還是值得的。
Ⅹ 資料庫中樹形圖的用法
資料庫中樹形圖的用法的用法你知道嗎?下面我就跟你們詳細介紹下資料庫中樹形圖的用法的用法,希望對你們有用。
資料庫中樹形圖的用法的用法如下:
樹形圖用於顯示按照樹形結構進行組織的數據,其用途比較廣泛,如計算機中的文件系統(Windows中的資源管理器)、企業或公司的組成結構等。我們知道在Windows下VB、PB、Delphi等工具提供了一個功能很強的樹型控制項TreeView,利用Treeview控制項可以方便地開發樹形圖。然而在網頁上實現樹形圖就不那麼容易了,現在在asp.net中利用微軟提供的Internet Explorer WebControls它使得網頁上的樹形圖開發與在Windows下一樣的方便,一樣的功能強大,甚至更靈活。
本文介紹用Internet Explorer WebControls開發樹形圖的方法,由於樹形圖結構較復雜,使用起來常不知如何下手。筆者結合最近剛為公司用ASP.NET編寫的應用程序管理器這一具體實例,詳細闡述在ASP.NET下如何將Internet Explorer WebControls的使用與資料庫聯系起來,實現數據分任意多層顯示,方便地進行增加、修改、刪除、移動操作。筆者希望通過對該實例的闡述,達到拋磚引玉的效果,與各位同仁相互交流,共同進步。
Internet Explorer WebControls不在VS.NET的標准Server Control中,要到微軟的站點上下載,下載地址是:
http://msdn.microsoft.com/downloads/samples/internet/default.asp?url=/Downloads/samples/Internet/ASP_DOT_NET_ServerControls/WebControls/default.asp
下載安裝後第一次使用時,要右擊工具箱Customize Toolbox…→.NET Framework Components中找到Micosoft.Web.UI.WebControls.Treeview後選中,這樣Treeview控制項就出現在工具箱中了。
一、樹的建立
具體方法是:創建一個資料庫,設計樹圖信息表TREE_INFO,包含NODEID、PARENTID、NODENAME、ADDErss、ICON欄位,其它欄位根據實際業務而定,節點名稱NODENAME將在樹型控制項的節點上顯示,NODEID欄位保存節點的唯一標識號,PARENTID表示當前節點的父節點號,標識號組成了一個“鏈表”,記錄了樹上節點的結構。設計一個Web窗體其上放置TreeView控制項。
PRivate Sub CreateDataSet()’建立數據集
Dim myConn As New SqlConnection()
Dim myCmd As New SqlCommand("select NODEID,NODENAME,PARENTID,ADDRESS,ICON from Tree_info", myConn)
Dim myDataAdapter As New SqlDataAdapter()
myConn.ConnectionString = application("connectstring")
myCmd.CommandText = ""
myCmd.Connection = myConn
myDataAdapter.SelectCommand = myCmd
myDataAdapter.Fill(ds, "tree")
End Sub
建樹的基本思路是:從根節點開始遞歸調用顯示子樹
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
CreateDataSet()
intiTree(TreeView1.Nodes, 0)
End Sub
Private Sub intiTree(ByRef Nds As TreeNodeCollection, ByVal parentId As Integer)
Dim dv As New DataView()
Dim drv As DataRowView
Dim tmpNd As TreeNode
Dim intId As Integer
dv.Table = ds.Tables("tree")
dv.RowFilter = "PARENTID=’" & parentId & "’"
For Each drv In dv
tmpNd = New TreeNode()
strId = drv("NODE_ID")
tmpNd.ID = strId
tmpNd.Text = drv("NODE_NAME ")
tmpNd.ImageUrl = drv("ICON").ToString
Nds.Add(tmpNd)
intiTree(Nds(Nds.Count - 1).Nodes, intId)
Next
End Sub
二、增加、刪除樹節點
單純在Treeview 上增加、刪除、修改節點只需用Nodes屬性的Add、 Remove、等方法即可,值得注意的地方是VS.NET中Treeview的Nodes集合與VS6.0中的區別,VS6.0中的是一個大的集合,而VS.NET中的是分層的每個Node下都有Nodes屬性。增加、刪除、修改樹節點時與VS6.0相比有很大差別,特別是刪除時。
Private Sub ButAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButAdd.Click’在選定的節點下添加子節點
Dim tmpNd As New TreeNode(), NdSel As TreeNode
tmpNd.ID = GetNewId()
NdSel = TreeView1.GetNodeFromIndex(TreeView1.SelectedNodeIndex)’選中的節點
tmpNd.Text = "新節點"
NdSel.Nodes.Add(tmpNd)
Dim myRow As DataRow
myRow = ds.Tables("tree").NewRow()
myRow("NODE_NAME") = tmpNd.ID
myRow("NODE_DESCRipT") = "新節點" & tmpNd.ID & "_" & NdSel.ID
myRow("PARENT_NAME") = NdSel.ID
ds.Tables("tree").Rows.Add(myRow)
End Sub
Private Sub ButDele_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles ButDele.Click’刪除選中的節點
Dim idx As String = TreeView1.SelectedNodeIndex()
GetNdCol(idx).Remove(TreeView1.GetNodeFromIndex(idx))
Dim dv As New DataView(), recNo As Integer
dv.Table = ds.Tables("tree")
dv.RowFilter= "NODEID=" & NdId
dv.Delete(0)
End Sub
Private Function GetNdCol(ByVal idx As String) As TreeNodeCollection
‘獲得選中節點的父節點的Nodes集合
Dim cnt As Integer, i As Integer
Dim tmpNds As TreeNodeCollection
Dim idxs() As String
idxs = Split(idx, ".")
cnt = UBound(idxs)
If cnt = 0 Then
tmpNds = TreeView1.Nodes
Else
tmpNds = TreeView1.Nodes(CInt(idxs(0))).Nodes
For i = 1 To cnt - 1
tmpNds = tmpNds(CInt(idxs(i))).Nodes
Next
End If
Return tmpNds
End Function
三、修改、移動樹節點
由於伺服器控制項不支持滑鼠拖動事件,所以不能象Windows程序那樣通過拖動移動節點,這里是通過選擇父節點的方式。移動是通過在原位置刪除,新位置添加實現的,要注意在刪除時先保存節點信息。
Private Sub TreeView1_SelectedIndexChange(ByVal sender As Object, ByVal e As Microsoft.Web.UI.WebControls.TreeViewSelectEventArgs) Handles TreeView1.SelectedIndexChange
Dim dv As New DataView()
dv.Table = ds.Tables("tree")
Dim tmpNd As TreeNode = TreeNdSel(e.OldNode), tmpNds As TreeNodeCollection
dv.RowFilter= "NODEID=" & tmpNd.ID
dv(0)("NODE_DESCRIPT") = Me.TextBox1.Text
dv(0)("ADDRESS") = Me.TextBox2.Text
dv(0)("TARGET") = Me.TextBox3.Text
dv(0)("ICON") = Me.TextBox4.Text
If dv(0)("PARENTID").ToString <> Me.DropDownList1.SelectedItem.Value Then
‘移動節點
dv(0)("PARENT_NAME") = Me.DropDownList1.SelectedItem.Value
If Me.DropDownList1.SelectedItem.Value = "ROOT" Then
tmpNds = TreeView1.Nodes
Else
tmpNds = FromIdToNode(Me.DropDownList1.SelectedItem.Value, TreeView1.Nodes).Nodes’新的父節點的Nodes集合
End If
GetNdCol(e.OldNode).Remove(tmpNd)
tmpNds.Add(tmpNd)
End If
tmpNd.Text = Me.TextBox1.Text
tmpNd.ImageUrl = Me.TextBox4.Text
tmpNd = TreeView1.GetNodeFromIndex(TreeView1.SelectedNodeIndex)
dv.RowFilter= "NODEID=" & tmpNd.ID
Me.TextBox1.Text = dv(0)("NODENAME").ToString
Me.TextBox2.Text = dv(0)("ADDRESS").ToString
Me.TextBox3.Text = dv(0)("TARGET").ToString
Me.TextBox4.Text = dv(0)("ICON").ToString
End Sub
Private Function FromIdToNode(ByVal ID As String, ByVal Nds As TreeNodeCollection) As TreeNode
‘由關鍵字查找節點
Dim i As Integer
Dim tmpNd As TreeNode, tmpNd1 As TreeNode
For Each tmpNd In Nds
If tmpNd.ID = ID Then
Return tmpNd
Exit Function
End If
tmpNd1 = FromIdToNode(ID, tmpNd.Nodes)
If Not (tmpNd1 Is Nothing) Then
Return tmpNd1
Exit Function
End If
Next
Return Nothing
End Function