2008-12-04 54 views
3

我目前正在重寫一個應用程序,教師可以在線規劃課程表。在PHP中使用最佳表示方式/深度樹(MySQL/XML /?)

該應用程序指導教師通過爲學生創建工作單元的過程。該工具目前在三種狀態下使用,但我們計劃獲得比這更大的作用。

該應用程序的主要抽獎卡之一是,所有的學生成果都預先加載到系統中。這允許教師搜索或瀏覽並選擇在每個工作單元中將滿足哪些結果。

當我最初設計系統時,我做了一個假設,即所有學生的成果都遵循相似的層次結構。也就是說,有命名嵌套容器,然後是結果。

我輸入的最初結果集是三層。因此我的數據庫具有以下結構:

=========================

表以粗體

H1

ID,名稱

H2

號,parent___id(h1_id),名稱

H3

ID,parent___id(h2_id),名稱

結果

ID,parent___id(h3_id),名稱

=========================

其他比明顯無法添加n /層次的層次結構還要難以在不遞歸查詢數據庫的情況下顯示所有標準的列表。

一旦學生的成績(和他們的父類別)被添加,他們沒有什麼理由以任何方式進行修改。主要的要求是它們很容易和有效的閱讀。

到目前爲止,來自不同學校/州/國家的所有學生成績都大致遵循了我的假設。這可能並非總是如此。

當然,所有現有數據都必須從當前數據庫傳輸。

鑑於以上所述,我存儲所有不同套學生成果的最佳方式是什麼?下面列出了我的一些想法。

  • 繼續使用數據庫中的4個表,選擇或者使用recusion或地段時加入

  • 使用嵌套組

  • XML(可能是全球性的XML文件的所有不同套或每個XML文件)

+0

請參閱我的答案http://stackoverflow.com/questions/192220/what-is-the-most-efficientelegant-way-to-parse-a-flat-table-into-a-tree#192462 – 2008-12-04 07:53:18

回答

6

我不知道你實際上需要4個表格。

如果您有一個跟蹤parent_id的表和一個可以有無限級別的級別。

結果

ID,PARENT_ID,級別,名稱

您可以使用遞歸遍歷樹的任何特定元素跟蹤(你實際上並不需要的水平,但它可以更容易查詢)。

替代方案是嵌套集。在這種情況下,你仍然會合併到一個表中,但是使用設置的東西來跟蹤級別。

要使用哪一個取決於您的應用程序。

讀密集型:嵌套集合

寫密集型:父樹啄

這是因爲與嵌套集合,你可以用一個單一的查詢,但在重新排序整棵樹的成本獲取整個樹每次插入一個新節點時。

當您剛剛跟蹤parent_id時,可以單獨移動或刪除節點。 PS:我對XML投票不支持。你有相同的遞歸問題,加上解析數據的開銷,以及將它存儲在數據庫或文件系統中(這會導致併發問題)。

+0

謝謝對於這些建議,有時候你只需要一個新的意見來指出那顯而易見的問題。 Cheers :) – Danny 2008-12-04 10:56:21

1

我同意另一張海報 - 嵌套集是我想的方式。

在這裏看到:

http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

它解釋的理論,並將其與你已經在使用 - 這是對鄰接扭轉真的。它顯示了全部的+/-,並且應該幫助您根據項目的所有細節做出決定。

我見過的另一件事(在CakePHP的樹行爲中)實際上是同時使用兩者。當然,它不是很好的表現,但在這個模型下,你插入/刪除的東西就像你在鄰接時一樣,然後有一個方法來重建左/右邊的值,讓你在嵌套中執行選擇集時尚。結果是你可以更容易地插入/刪除。

http://book.cakephp.org/view/91/Tree

+0

我遇到過一個CI類,它允許組合嵌套集和鄰接模型,與您可能嘗試鏈接的cakephp版本類似。 我會回來的結果。 – Danny 2008-12-04 10:56:55

0

還有另一種方式是,也許比這裏所描述的嵌套組等模式不是「智能」數據庫來處理樹木,但是這確實是高效和方便:

代替存儲項目的水平(或深度),您可以存儲的完整路徑樹,像這樣:

A 
    B 
    C 
    D 
    E 

將存儲這樣的:

item | parent | path 
---------------------------- 
A  | NULL | A 
B  | A  | A--B 
C  | A  | A--C 
D  | C  | A--C--D 
E  | A  | A--E 

那麼你可以easyly得到:

  • (純SQL)與其中母公司=「」條款
  • (純SQL)的所有直接和間接的孩子用其中一個項目的所有直接子路徑LIKE的母公司 - %'子句
  • (PHP)的節點的深度(計數(爆炸( ' - ',$ PATH))

這些功能都夠用了在大多數情況下,和相當高效,即使有幾個子游戲,只要a你創建好的指數(PK,父母指數,路徑指數)。當然,這個解決方案要求刪除/移動節點來更新路徑...

我希望這有助於!