YbSoftwareFactory 代碼生成插件【十八】:樹形結構下的查詢排序的數據庫設計

    樹形結構的排序在中國特點下十分廣泛也很是重要,例如常說的五大班子,黨委>人大>政府>政協>紀委,每一個班子下還有部門,崗位,人員,最終排列的順序一般須要按權力大小、重要性等進行排列,順序排列很差但是重大的罪過,領導很生氣,後果很嚴重。這種排序方式本質上就是典型的樹形結構深度排序,但在數據庫中很難直接經過SQL語句簡單高效地進行處理,更不用說還要支持不一樣類型數據庫了。html

    當前解決此類問題,主要有兩種方法。數據庫

    1. 排序碼方式併發

  • 原理:在每一個樹形節點上均設置一個排序碼,排序碼一般是一個字符串並存入數據庫,例如

    

  • 優勢:只需一個冗餘字段,數據庫中存儲顯示直觀,查詢和排序既方便也高效,無需遞歸,只用一條查詢語句便可獲得某個根節點及其全部子孫節點的先序遍歷。例如須要查詢四川下全部地區並進行排序,使用SQL 語句「LIKE ‘0510%’ ORDER BY 地區」 便可查詢並排列出結果。
  • 缺點:一般在錄入樹形節點時須要人工指定排序碼,在同層節點間插入新的節點時須要考慮編碼重複致使排序失效的問題;後續如需對排序順序進行置頂、前移、後移、置底等相似的調整則很是不方便;同時這種編碼方案因爲層信息位數的限制,限制了每層所能容許的最大子節點數量及最大層數。

    2. 左右值編碼ide

  • 原理:請參考「採用左右值編碼來存儲無限分級樹形結構的數據庫表設計
  • 優勢:無需人工設定排序編碼,可交由系統計算後生成;一樣無需遞歸,同時還能實現無限分級;查詢條件基於整形數字比較的,效率很高;還能方便地進行先序列表,添加,修改,刪除,同層平移等常規操做。
  • 缺點:主要是顯示不直觀,維護不方便,須要考慮數據庫的併發操做。因爲這種左右值編碼的方式和常見的阿拉伯數字直觀排序不一樣,再加上節點在樹中的層次,順序不能直觀顯示出來,而必須經過簡單的公式計算後獲得,須要花費必定的時間對其數學模型進行深刻理解。並且,採用該方案編寫相關存儲過程,新增,刪除,同層平移節點須要對整個樹進行查詢修改,由此致使的代碼複雜度,耦合度較高,修改維護的風險較高。數據庫中某個節點的編碼被錯誤修改可能就會致使總體排序失敗,但很難及時方便地定位到具體的錯誤緣由。本設計須要兩個冗餘字段。

    本文介紹的設計方式則是前文介紹的權限模型中組織機構樹所採用的排序碼+排序值方式:http://www.cnblogs.com/gyche/p/3670179.html編碼

    排序碼+排序值spa

  • 原理

    1)數據庫表結構的設計中增長兩個排序字段,其中一個字段存儲排序碼,類型爲字符串,另外一個字段存儲排序值,類型爲浮點型。排序碼最終參與SQL語句的查詢和排序結果的生成;排序值爲輔助字段,主要用於同層次節點間排序順序的比較、排序順序的調整修改等並最終根據其值格式化生成排序碼,該字段並不直接參與SQL語句的查詢和排序,主要是在對排序順序進行調整時很是有用。.net

    2)新增節點時,查找要插入節點所在的父節點的排序碼和父節點下全部直接子節點的最大排序值並加1得出實際排序值(此處假想添加的節點老是排在同層節點的最後),根據該排序值格式化出固定長度的排序碼並和父節點的排序碼組合,中間使用「/」字符隔開,生成實際的排序碼。例如,父結點的排序碼爲「/000000000000000000129.」,當前計算出的排序值爲320,對應的排序值則爲:「000000000000000000320.」,則最終的排序碼就應該是「/000000000000000000129./000000000000000000320.」。設計

    此處須要注意的是,排序值爲負數的狀況下,須要使用浮點值所容許的最小值-去排序值來格式化生成排序碼(由於最終排序使用的是字符串比較),不然排序值爲負數的狀況下使用字符串比較進行排序就會出現問題,生成排序碼的程序代碼以下:orm

        /// <summary>
        /// 格式化生成排序碼
        /// </summary>
        /// <param name="parentOrderCode">父排序碼</param>
        /// <param name="displayOrder">排序值</param>
        /// <returns>生成的排序碼</returns>
        internal override string FormatOrderCode(string parentOrderCode, decimal displayOrder)
        {
            if (displayOrder < decimal.Zero)
            {
                displayOrder = decimal.MinValue - displayOrder;
            }
            //可根據須要調整生成排序碼的格式和長度
            var orderCode = string.Format("{0:000000000000000000000.000000000000000000}", displayOrder).Replace('-', '#').TrimEnd(new[] { '0' });
            return string.Format("{0}/{1}", parentOrderCode, orderCode); ;
        }
  • 優勢:具備方式1的全部優勢,數據庫中存儲顯示直觀,查詢和排序既方便也高效,無需遞歸,只用一條查詢語句便可獲得某個根節點及其全部子孫節點的先序遍歷;並且無需人工設定排序編碼,可交由系統計算後生成;同時後續調整排序順序也很是方便,只需從新計算該節點要調整後的排序值並從新生成排序碼,而後使用各類數據庫都廣泛支持,而且語法也基本同樣的「REPLACE」 SQL 語句批量替換排序碼字符串便可完成當前節點及下屬全部子節點的排序調整任務,對排序的置頂、前移、後移、置底等實現都很是簡單,例以下圖的效果,乃至於實如今界面上以拖拽的方式對每一個樹節點進行排序順序的調整,也是很是方便的。
        
  • 缺點:須要兩個冗餘字段,調整節點順序後,系統需自動對當前節點即下屬節點的排序碼字段的值進行維護;同時也和方式1同樣,這種編碼方案因爲層信息位數的限制,限制了每層所能容許的最大子節點數量及最大層數(例如排序碼字段在數據庫中設計的字符串長度爲4000,每層節點固定長度爲40的話,最大層數可容許爲100層,但在實際應用中,超過十層的樹形節點已經是很是罕見的)。

    附 - 排序在線演示:http://pjdemo.yellbuy.com/htm

相關文章
相關標籤/搜索