當前位置:首頁 » 操作系統 » 資料庫分類設計

資料庫分類設計

發布時間: 2022-07-01 00:09:28

資料庫設計主要包括哪幾部分,分別包括哪些內容

資料庫設計主要包括需求分析、概念結構設計、邏輯結構設計、物理結構設計、資料庫的實施和資料庫的運行和維護,具體內容如下:

1、需求分析

內容:調查和分析用戶的業務活動和數據的使用情況,弄清所用數據的種類、范圍、數量以及它們在業務活動中交流的情況,確定用戶對資料庫系統的使用要求和各種約束條件等,形成用戶需求規約。

2、概念設計

內容:對用戶要求描述的現實世界,通過對其中諸處的分類、聚集和概括,建立抽象的概念數據模型。這個概念模型應反映現實世界各部門的信息結構、信息流動情況、信息間的互相制約關系以及各部門對信息儲存、查詢和加工的要求等。

3、邏輯設計

內容:主要工作是將現實世界的概念數據模型設計成資料庫的一種邏輯模式,即適應於某種特定資料庫管理系統所支持的邏輯數據模式。與此同時,可能還需為各種數據處理應用領域產生相應的邏輯子模式。這一步設計的結果就是所謂「邏輯資料庫」。

4、物理設計

內容:根據特定資料庫管理系統所提供的多種存儲結構和存取方法等依賴於具體計算機結構的各項物理設計措施,對具體的應用任務選定最合適的物理存儲結構(包括文件類型、索引結構和數據的存放次序與位邏輯等)、存取方法和存取路徑等。

5、驗證設計

內容:收集數據並具體建立一個資料庫,運行一些典型的應用任務來驗證資料庫設計的正確性和合理性。一般,一個大型資料庫的設計過程往往需要經過多次循環反復。當設計的某步發現問題時,可能就需要返回到前面去進行修改。

6、運行與維護設計

內容:在資料庫系統正式投入運行的過程中,必須不斷地對其進行調整與修改。除了關系型資料庫已有一套較完整的數據範式理論可用來部分地指導資料庫設計之外,尚缺乏一套完善的資料庫設計理論、方法和工具,以實現資料庫設計的自動化或互動式的半自動化設計。

(1)資料庫分類設計擴展閱讀:

重要性

1、有利於資源節約

對計算機軟體資料庫設計加以重視不僅可減少軟體後期的維修,達到節約人力與物力的目的,同時還有利於軟體功能的高效發揮。

2、有利於軟體運行速度的提高

高水平的資料庫設計可滿足不同計算機軟體系統對於運行速度的需求,而且還可充分發揮並實現系統功能。計算機軟體性能提高後,系統發出的運行指令在為用戶提供信息時也將更加快速有效,軟體運行速度自然得以提高。

3、有利於軟體故障的減少

加強資料庫設計可有效減少軟體故障的發生幾率,推動計算機軟體功能的實現。

② 資料庫有哪些類型

資料庫有兩種類型,分別是關系型資料庫與非關系型資料庫。

資料庫,簡而言之可視為電子化的文件櫃——存儲電子文件的處所,用戶可以對文件中的數據進行新增、截取、更新、刪除等操作。

關系型資料庫主要有:

Oracle、DB2、Microsoft sql Server、Microsoft Access、MySQL等等。

非關系型資料庫主要有:

NoSql、Cloudant、MongoDb、redis、HBase等等。

(2)資料庫分類設計擴展閱讀

非關系型資料庫的優勢:

1、性能高:NOSQL是基於鍵值對的,可以想像成表中的主鍵和值的對應關系,而且不需要經過SQL層的解析,所以性能非常高。

2、可擴展性好:同樣也是因為基於鍵值對,數據之間沒有耦合性,所以非常容易水平擴展。

關系型資料庫的優勢:

1、可以復雜查詢:可以用SQL語句方便的在一個表以及多個表之間做非常復雜的數據查詢。

2、事務支持良好:使得對於安全性能很高的數據訪問要求得以實現。

③ 如何進行文章分類和標簽的資料庫設計

幾乎在所有web項目中,都涉及文章分類和標簽的設計,應該說這是一個比較常見、典型的案例。站長並不保證我的思路就是最好的,只是分享出來大家一起交流一下,互相促進與提高。我們假設的開發項目是一個博客系統,最核心的部分就是與文章相關的,那麼我們今天討論如何設計博客系統的文章分類和標簽。1、首先,分類和標簽都是要和具體的文章相關聯的,當然也可能一些文章既沒有分類也沒有標簽,這一點是大家在寫查詢的時候容易疏忽的地方。因為我們的第一感覺就是,在查詢文章列表的時候關聯分類表,查出所有的文章和分類,對應關系一般是文章表的分類id對應分類表的id,使用where子句進行限定。這里就存在一個問題了,由於使用了where子句,那麼只能查詢有分類的文章,而沒有分類的文章就查詢不到了。這時候怎麼辦?應該使用連接查詢,left join,這要沒有分類的文章,在文章分類id那一欄會顯示null。通常我們只使用left join,而很少使用right join。2、一般,一篇文章最好只對應一個分類,當然如果你想要對應多個分類也可以。但站長並不提倡,文章在多個分類中重復會給人很不專業的感覺,即使有些文章可能確實設計到多方面的內容,那麼你應就其中的側重點來分類。而標簽就不一樣了,一篇文章可能有多個標簽。這就意味著我們無法靠一個sql語句既查出所有文章的分類和標簽,又做到查詢結果中的文章id不重復。通常我們需要把查詢出來的結果直接循環出來,那麼這個結果一般是二維數組,第二維的都存儲了唯一一篇文章的相關信息。但是,標簽和文章是多對一的關系,多個標簽對應一篇文章,如果你只用一條sql語句的話,那麼我們查詢出來的結果,當然也是多行,這不符合我們目標數據的要求。應此,需要在查詢完文章和分類之後,在前面結果的基礎上再查詢一次文章標簽,把兩次的結果結合起來,存在數組中,這是對應文章列表頁面的查詢方法。對於具體文章頁面,可以分兩次查詢。好了,還沒有給出具體的資料庫設計,就先說了如何查詢結果,相信大家也看煩了,下面就舉例說明:一、文章表:post,欄位如下:id【唯一標識】,aid【作者id】,title【標題】,content【內容】,cid【分類id】二、分類表,category,欄位如下:id【唯一標識,與post表的cid關聯】,name【分類名】三、標簽表,tag,欄位如下:id【唯一標識】,name【標簽名】四、標簽與文章對應關系表,tag_relationship,欄位如下:id【唯一標識】,postid【文章id,與post表的id關聯】,tagid【標簽id,tag表的id關聯】有朋友可能會問:為什麼要單獨用一個表來存儲文章與標簽的對應關系,為什麼不可以直接在tag表中增加一個文章id欄位呢,比如:tag表:id,postid,name這樣做的話,並不是不可以,但是,由於一篇文章對應多個標簽,所以name欄位的值會出現很多重復,比如一篇文章,假設文章id為1,有2個標簽,php和mysql,那麼在tag表會這樣存儲:id:1,postid:1,name:phpid2,postid:1,name:mysql另一篇文章,假設id為2,有2個標簽,也是php和mysql,那麼在tag表中它會這樣存儲:id:3,postid:2,name:phpid4,postid:2,name:mysql大家很快就發現了問題,這樣的設計name欄位也就是標簽的名稱在同一張表中可能會大量重復。但是這樣設計的好處是,如果你要查詢一個標簽下有多少篇文章,只要單獨查這個表就可以了,比如要查詢含有php標簽的文章有多少篇,只需要select count(name) �0�2from tag where name=』php』,就可以查出來。不好的地方是,如果要查詢所有標簽的集合,使用這種設計需要使用group by name語句來去除重復的行。如果用之前的那種,只需要select * from tag就可以了。一時之間,好像不太好取捨。這兩種設計都會有數據冢余,第一種tag_relationship表中,存在tagid欄位的重復;而這兩種設計又都有各自的好處。那麼我們到底該怎麼選擇呢?站長也說不好,所以無法為大家下結論。但是站長在研究wordpress數據結構的時候,發現wp是採用的單獨建表存儲文章與標簽對應關系的方式。另外,如何設計有時候也是取決具體功能的需求的,所以這個問題就留給大家一起來討論吧~ 標簽:分類和標簽, 博客資料庫設計

④ 分類信息資料庫設計

運用Visual FoxPro開發學生管理系統摘要:學生管理系統的功能主要可分為系統、編輯、查詢及統計.為了簡化系統結構,方便使用者操作,可以採用Visual FoxPro的頁框技術.一個資料庫應用系統的優劣,在很大程度上取決於資料庫的結構設計,且數據量越大效果越明顯.關鍵詞:面向對象編程;學生管理系統;流程;Visual FoxPro目前,很多學校的學生管理工作基本上還是採用手工方式,因沒有管理軟體而沒有實現管理工作自動化.對於一些購買的軟體,由於開發者缺乏學生管理的經驗,這些軟體有的不易操作,有的功能不夠完善,升級維護也不方便.各學校如果能夠根據實際情況,充分利用新技術自行開發適合本校管理模式的學生管理系統,既可以提高工作效率,又能節省資金,升級維護也十分方便.本文探討如何運用Visual FoxPro開發學生管理系統.1系統功能及其人機界面設計1.1系統功能針對學校學生管理工作的特點,筆者認為學生管理系統應具備以下基本功能.1.1.1主要功能其中,系統功能主要實現系統資料庫的打開及關閉、自動生成庫存記錄、系統數據的備份及恢復、列印各類統計報表等;編輯功能主要實現資料庫記錄的增加、刪除和修改以及系統基本信息的設置;查詢及統計功能主要實現學生有關信息的查詢、人事綜合查詢、快速定位查詢和有關信息的分類統計.1.1.2輔助功能包括:系統作實際物理刪除時給出提示,以防止誤刪除;資料庫整理,將不符合規范的記錄自動清除;進入系統時的身份驗證.1.1.3系統資料庫主要包括:學生基本情況、學生成績、課程設置、考勤情況、任課教師情況等資料庫文件.1.2系統人機界面為了簡化系統結構以及方便使用者操作,可以不採用通常的菜單編寫方式,而採用Visual FoxPro的頁框技術,將系統幾大功能分別放置在頁框的5個Page中,使用人員可以在每一頁中對相應數據進行全面的操作和管理.這些操作包括順序查詢、綜合查詢、新增、刪除、修改等.每頁下的綜合查詢按鈕可彈出多層查詢菜單,在這些菜單中可實現一系列的綜合查詢、統計、列印統計結果、定位等功能.系統維護頁框主要實現對系統原始數據的一些操作,包括備份系統數據到指定介質中、從備份資料中恢復系統數據、自動形成歷史數據的備份記錄和修改系統基本參數.以上功能的實現可增強軟體的靈活性和數據的安全性.2系統開發工作流程運用資料庫設計應用系統時,如果把精力放在表單及報表設計上而不重視資料庫本身的設計,甚至邊進行程序編制邊修改資料庫結構,則極有可能導致存儲空間的浪費、系統效率差、數據不一致、系統維護不方便等不良後果.事實上,一個資料庫應用系統的優劣,在很大程度上取決於資料庫的結構設計,且數據量越大效果越明顯.因此,應將資料庫設計流程作為系統開發的重點.2.1系統功能目標分析本階段的工作是詳細調查研究學生管理工作的流程,整理和概括日常工作的內容、步驟、目標,明確所要開發的軟體應有的基本功能、一般功能、高級功能以及現在暫時不用但以後可能需要的補充功能.2.2設計資料庫設計資料庫是應用系統設計中很關鍵的一個工作流程.為了設計出一個高效率、易於維護和升級的資料庫,在進行資料庫設計時應該做好以下工作.2.2.1數據需求分析數據需求分析的目的是找出應用系統需要用到的所有數據項(數據表中的欄位),即要找出准備放入資料庫的所有數據項,這些數據項在將來的表單及報表設計中都要用到.為了避免日後修改數據結構,要盡可能在此階段列舉出全部、完整的數據項.2.2.2分析數據項當完成所有數據項的收集和羅列後,要找出真正需要放入數據表的數據項,也就是要確定數據表的欄位並將其放入數據表中.在確定數據表欄位時應把握以下原則:①不要包含可由其他欄位計算(推導)得來的欄位;②不要包含可自行計算得來的欄位;③以最小的邏輯組合單位儲存數據;④不可包含內容相同但名稱不同的欄位.2.2.3資料庫規范化為了避免數據重復或不一致的情況發生,可將上一步工作所得到的數據表分割成數個大小適當、相互關聯、「規范化」的數據表.2.3設計程序基本流程框圖一個簡單明了的程序流程可以極大地精簡系統編制的工作量,同時又能讓使用者操作起來得心應手.如果程序流程設計得過於復雜、交叉作業太多,必然導致操作人員使用上的不便.設計時應該明確系統使用對象和他們的工作習慣,盡量簡化流程,使操作者在當前GUI下實

⑤ 資料庫分區的分類

分區主要有兩種形式://這里一定要注意行和列的概念(row是行,column是列)
水平分區(Horizontal Partitioning)
這種形式分區是對表的行進行分區,通過這樣的方式不同分組裡面的物理列分割的數據集得以組合,從而進行個體分割(單分區)或集體分割(1個或多個分區)。所有在表中定義的列在每個數據集中都能找到,所以表的特性依然得以保持。
舉個簡單例子:一個包含十年發票記錄的表可以被分區為十個不同的分區,每個分區包含的是其中一年的記錄。(朋奕註:這里具體使用的分區方式我們後面再說,可以先說一點,一定要通過某個屬性列來分割,譬如這里使用的列就是年份)
垂直分區(Vertical Partitioning)
這種分區方式一般來說是通過對表的垂直劃分來減少目標表的寬度,使某些特定的列被劃分到特定的分區,每個分區都包含了其中的列所對應的行。
舉個簡單例子:一個包含了大text和BLOB列的表,這些text和BLOB列又不經常被訪問,這時候就要把這些不經常使用的text和BLOB了劃分到另一個分區,在保證它們數據相關性的同時還能提高訪問速度。
在資料庫供應商開始在他們的資料庫引擎中建立分區(主要是水平分區)時,DBA和建模者必須設計好表的物理分區結構,不要保存冗餘的數據(不同表中同時都包含父表中的數據)或相互聯結成一個邏輯父對象(通常是視圖)。這種做法會使水平分區的大部分功能失效,有時候也會對垂直分區產生影響。

⑥ 資料庫設計-物品分類-方法選擇

物品id,物品名,其他信息。。。
物品id,類別
有多少個類別就建多少條記錄
例如:
物品id,類別
001 1
001 2
都這一點數據對資料庫來說,不算什麼,這個是隨著物品的增加而增加,
幅度不會很大

⑦ 如何進行高效的文章分類和標簽的資料庫設計

幾乎在所有web項目中,都涉及文章分類和標簽的設計,應該說這是一個比較常見、典型的案例。站長並不保證我的思路就是最好的,只是分享出來大家一起交流一下,互相促進與提高。我們假設的開發項目是一個博客系統,最核心的部分就是與文章相關的,那麼我們今天討論如何設計博客系統的文章分類和標簽。1、首先,分類和標簽都是要和具體的文章相關聯的,當然也可能一些文章既沒有分類也沒有標簽,這一點是大家在寫查詢的時候容易疏忽的地方。因為我們的第一感覺就是,在查詢文章列表的時候關聯分類表,查出所有的文章和分類,對應關系一般是文章表的分類id對應分類表的id,使用where子句進行限定。這里就存在一個問題了,由於使用了where子句,那麼只能查詢有分類的文章,而沒有分類的文章就查詢不到了。這時候怎麼辦?應該使用連接查詢,left join,這要沒有分類的文章,在文章分類id那一欄會顯示null。通常我們只使用left join,而很少使用right join。2、一般,一篇文章最好只對應一個分類,當然如果你想要對應多個分類也可以。但站長並不提倡,文章在多個分類中重復會給人很不專業的感覺,即使有些文章可能確實設計到多方面的內容,那麼你應就其中的側重點來分類。而標簽就不一樣了,一篇文章可能有多個標簽。這就意味著我們無法靠一個sql語句既查出所有文章的分類和標簽,又做到查詢結果中的文章id不重復。通常我們需要把查詢出來的結果直接循環出來,那麼這個結果一般是二維數組,第二維的都存儲了唯一一篇文章的相關信息。但是,標簽和文章是多對一的關系,多個標簽對應一篇文章,如果你只用一條sql語句的話,那麼我們查詢出來的結果,當然也是多行,這不符合我們目標數據的要求。應此,需要在查詢完文章和分類之後,在前面結果的基礎上再查詢一次文章標簽,把兩次的結果結合起來,存在數組中,這是對應文章列表頁面的查詢方法。對於具體文章頁面,可以分兩次查詢。好了,還沒有給出具體的資料庫設計,就先說了如何查詢結果,相信大家也看煩了,下面就舉例說明:一、文章表:post,欄位如下:id【唯一標識】,aid【作者id】,title【標題】,content【內容】,cid【分類id】二、分類表,category,欄位如下:id【唯一標識,與post表的cid關聯】,name【分類名】三、標簽表,tag,欄位如下:id【唯一標識】,name【標簽名】四、標簽與文章對應關系表,tag_relationship,欄位如下:id【唯一標識】,postid【文章id,與post表的id關聯】,tagid【標簽id,tag表的id關聯】有朋友可能會問:為什麼要單獨用一個表來存儲文章與標簽的對應關系,為什麼不可以直接在tag表中增加一個文章id欄位呢,比如:tag表:id,postid,name這樣做的話,並不是不可以,但是,由於一篇文章對應多個標簽,所以name欄位的值會出現很多重復,比如一篇文章,假設文章id為1,有2個標簽,php和mysql,那麼在tag表會這樣存儲:id:1,postid:1,name:phpid2,postid:1,name:mysql另一篇文章,假設id為2,有2個標簽,也是php和mysql,那麼在tag表中它會這樣存儲:id:3,postid:2,name:phpid4,postid:2,name:mysql大家很快就發現了問題,這樣的設計name欄位也就是標簽的名稱在同一張表中可能會大量重復。但是這樣設計的好處是,如果你要查詢一個標簽下有多少篇文章,只要單獨查這個表就可以了,比如要查詢含有php標簽的文章有多少篇,只需要select count(name) 02from tag where name=』php』,就可以查出來。不好的地方是,如果要查詢所有標簽的集合,使用這種設計需要使用group by name語句來去除重復的行。如果用之前的那種,只需要select * from tag就可以了。一時之間,好像不太好取捨。這兩種設計都會有數據冢余,第一種tag_relationship表中,存在tagid欄位的重復;而這兩種設計又都有各自的好處。那麼我們到底該怎麼選擇呢?站長也說不好,所以無法為大家下結論。但是站長在研究wordpress數據結構的時候,發現wp是採用的單獨建表存儲文章與標簽對應關系的方式。另外,如何設計有時候也是取決具體功能的需求的,所以這個問題就留給大家一起來討論吧~ 標簽:分類和標簽, 博客資料庫設計

⑧ 商品分類的資料庫是怎麼設計的以滿足查詢的高效

這個三個表就應該夠了吧,一個是商品大類表,一個是品牌表,另外是商品詳細信息表
商品類別表:
ClassID
ClassName
ParentID //這個商品類歸屬的上個大類,也就是滿足你的多級分類要求

舉個例子 假設說你的鞋子分類id是1,那下屬的小類舉例說女涼鞋,她的ParentID就是1,明白?

品牌表:
BrandID
BrandName
BrandDescription

商品詳細信息表:
GoodId
ClassID
BrandID
GoodName
GoodDescription
GoodURl
還有其他你想加的屬性

⑨ 資料庫分為哪幾類

常用資料庫
1. IBM 的DB2
作為關系資料庫領域的開拓者和領航人,IBM在1997年完成了System R系統的原型,1980年開始提供集成的資料庫伺服器—— System/38,隨後是SQL/DSforVSE和VM,其初始版本與SystemR研究原型密切相關。DB2 forMVSV1 在1983年推出。該版本的目標是提供這一新方案所承諾的簡單性,數據不相關性和用戶生產率。1988年DB2 for MVS 提供了強大的在線事務處理(OLTP)支持,1989 年和1993 年分別以遠程工作單元和分布式工作單元實現了分布式資料庫支持。最近推出的DB2 Universal Database 6.1則是通用資料庫的典範,是第一個具備網上功能的多媒體關系資料庫管理系統,支持包括Linux在內的一系列平台。
2. Oracle
Oracle 前身叫SDL,由Larry Ellison 和另兩個編程人員在1977創辦,他們開發了自己的拳頭產品,在市場上大量銷售,1979 年,Oracle公司引入了第一個商用SQL 關系資料庫管理系統。Oracle公司是最早開發關系資料庫的廠商之一,其產品支持最廣泛的操作系統平台。目前Oracle關系資料庫產品的市場佔有率名列前茅。
3. Informix
Informix在1980年成立,目的是為Unix等開放操作系統提供專業的關系型資料庫產品。公司的名稱Informix便是取自Information 和Unix的結合。Informix第一個真正支持SQL語言的關系資料庫產品是Informix SE(StandardEngine)。InformixSE是在當時的微機Unix環境下主要的資料庫產品。它也是第一個被移植到Linux上的商業資料庫產品。
4. Sybase
Sybase公司成立於1984年,公司名稱「Sybase」取自「system」和 「database」 相結合的含義。Sybase公司的創始人之一Bob Epstein 是Ingres 大學版(與System/R同時期的關系資料庫模型產品)的主要設計人員。公司的第一個關系資料庫產品是1987年5月推出的Sybase SQLServer1.0。Sybase首先提出Client/Server 資料庫體系結構的思想,並率先在Sybase SQLServer 中實現。
5. SQL Server
1987 年,微軟和 IBM合作開發完成OS/2,IBM 在其銷售的OS/2 ExtendedEdition 系統中綁定了OS/2Database Manager,而微軟產品線中尚缺少資料庫產品。為此,微軟將目光投向Sybase,同Sybase 簽訂了合作協議,使用Sybase的技術開發基於OS/2平台的關系型資料庫。1989年,微軟發布了SQL Server 1.0 版。
6. PostgreSQL
PostgreSQL 是一種特性非常齊全的自由軟體的對象——關系性資料庫管理系統(ORDBMS),它的很多特性是當今許多商業資料庫的前身。PostgreSQL最早開始於BSD的Ingres項目。PostgreSQL 的特性覆蓋了SQL-2/SQL-92和SQL-3。首先,它包括了可以說是目前世界上最豐富的數據類型的支持;其次,目前PostgreSQL 是唯一支持事務、子查詢、多版本並行控制系統、數據完整性檢查等特性的唯一的一種自由軟體的資料庫管理系統.
7.mySQL
mySQL是一個小型關系型資料庫管理系統,開發者為瑞典MySQL AB公司。在2008年1月16號被Sun公司收購。目前MySQL被廣泛地應用在Internet上的中小型網站中。由於其體積小、速度快、總體擁有成本低,尤其是開放源碼這一特點,許多中小型網站為了降低網站總體擁有成本而選擇了MySQL作為網站資料庫。MySQL的官方網站的網址是: www.mysql.com

⑩ 資料庫設計中為什麼進行分類編碼設計分類的方法是什麼

分類演算法要解決的問題

在網站建設中,分類演算法的應用非常的普遍。在設計一個電子商店時,要涉及到商品分類;在設計發布系統時,要涉及到欄目或者頻道分類;在設計軟體下載這樣的程序時,要涉及到軟體的分類;如此等等。可以說,分類是一個很普遍的問題。

我常常面試一些程序員,而且我幾乎毫無例外地要問他們一些關於分類演算法的問題。下面的舉幾個我常常詢問的問題。你認為你可以很輕松地回答么?

1、分類演算法常常表現為樹的表示和遍歷問題。那麼,請問:如果用資料庫中的一個Table來表達樹型分類,應該有幾個欄位?

2、如何快速地從這個Table恢復出一棵樹?

3、如何判斷某個分類是否是另一個分類的子類?

4、如何查找某個分類的所有產品?

5、如何生成分類所在的路徑。

6、如何新增分類?

在不限制分類的級數和每級分類的個數時,這些問題並不是可以輕松回答的。本文試圖解決這些問題。

分類的數據結構

我們知道:分類的數據結構實際上是一棵樹。在《數據結構》課程中,大家可能學過Tree的演算法。由於在網站建設中我們大量使用資料庫,所以我們將從Tree在資料庫中的存儲談起。

為簡化問題,我們假設每個節點只需要保留Name這一個信息。我們需要為每個節點編號。編號的方法有很多種。在資料庫中常用的就是自動編號。這在Access、SQL Server、Oracle中都是這樣。假設編號欄位為ID。

為了表示某個節點ID1是另外一個節點ID2的父節點,我們需要在資料庫中再保留一個欄位,說明這個分類是屬於哪個節點的兒子。把這個欄位取名為FatherID。如這里的ID2,其FatherID就是ID1。

這樣,我們就得到了分類Catalog的數據表定義:

Create Table [Catalog](

[ID] [int] NOT NULL,

[Name] [nvarchar](50) NOT NULL,

[FatherID] [int] NOT NULL

);

約定:我們約定用-1作為最上面一層分類的父親編碼。編號為-1的分類。這是一個虛擬的分類。它在資料庫中沒有記錄。

如何恢復出一棵樹

上面的Catalog定義的最大優勢,就在於用它可以輕松地恢復出一棵樹?分類樹。為了更清楚地展示演算法,我們先考慮一個簡單的問題:怎樣顯示某個分類的下一級分類。我們知道,要查詢某個分類FID的下一級分類,SQL語句非常簡單:

select Name from catalog where FatherID=FID

顯示這些類別時,我們可以這樣:

<%

REM oConn---資料庫連接,調用GetChildren時已經打開

REM FID-----當前分類的編號

Function GetChildren(oConn,FID)

strSQL = "select ID,Name from catalog where FatherID="&FID

set rsCatalog = oConn.Execute(strSQL)

%>

<UL>

<%

Do while not rsCatalog.Eof

%>

<LI><%=rsCatalog("Name")%>

<%

Loop

%>

</UL>

<%

rsCatalog.Close

End Function

%>

現在我們來看看如何顯示FID下的所有分類。這需要用到遞歸演算法。我們只需要在GetChildren函數中簡單地對所有ID進行調用:GetChildren(oConn,Catalog(「ID」))就可以了。

<%

REM oConn---資料庫連接,已經打開

REM FID-----當前分類的編號

Function GetChildren(oConn,FID)

strSQL = "select Name from catalog where FatherID="&FID

set rsCatalog = oConn.Execute(strSQL)

%>

<UL>

<%

Do while not rsCatalog.Eof

%>

<LI><%=rsCatalog("Name")%>

<%=GetChildren(oConn,Catalog("ID"))%>

<%

Loop

%>

</UL>

<%

rsCatalog.Close

End Function

%>

修改後的GetChildren就可以完成顯示FID分類的所有子分類的任務。要顯示所有的分類,只需要如此調用就可以了:

<%

REM strConn--連接資料庫的字元串,請根據情況修改

set oConn = Server.CreateObject("ADODB.Connection")

oConn.Open strConn

=GetChildren(oConn,-1)

oConn.Close

%>

如何查找某個分類的所有產品

現在來解決我們在前面提出的第四個問題。第三個問題留作習題。我們假設產品的數據表如下定義:

Create Table Proct(

[ID] [int] NOT NULL,

[Name] [nvchar] NOT NULL,

[FatherID] [int] NOT NULL

);

其中,ID是產品的編號,Name是產品的名稱,而FatherID是產品所屬的分類。對第四個問題,很容易想到的辦法是:先找到這個分類FID的所有子類,然後查詢所有子類下的所有產品。實現這個演算法實際上很復雜。代碼大致如下:

<%

Function GetAllID(oConn,FID)

Dim strTemp

If FID=-1 then

strTemp = ""

else

strTemp =","

end if

strSQL = "select Name from catalog where FatherID="&FID

set rsCatalog = oConn.Execute(strSQL)

Do while not rsCatalog.Eof

strTemp=strTemp&rsCatalog("ID")&
GetAllID(oConn,Catalog("ID")) REM 遞歸調用

Loop

rsCatalog.Close

GetAllID = strTemp

End Function

REM strConn--連接資料庫的字元串,請根據情況修改

set oConn = Server.CreateObject("ADODB.Connection")

oConn.Open strConn

FID = Request.QueryString("FID")

strSQL = "select top 100 * from Proct
where FatherID in ("&GetAllID(oConn,FID)&")"

set rsProct=oConn.Execute(strSQL)

%>

<UL><%

Do while not rsProct.EOF

%>

<LI><%=rsProct("Name")%>

<%

Loop

%>

</UL>

<%rsProct.Close

oConn.Close

%>

這個演算法有很多缺點。試列舉幾個如下:

1、 由於我們需要查詢FID下的所有分類,當分類非常多時,演算法將非常地不經濟,而且,由於要構造一個很大的strSQL,試想如果有1000個分類,這個strSQL將很大,能否執行就是一個問題。

2、 我們知道,在SQL中使用In子句的效率是非常低的。這個演算法不可避免地要使用In子句,效率很低。

我發現80%以上的程序員鍾愛這樣的演算法,並在很多系統中大量地使用。細心的程序員會發現他們寫出了很慢的程序,但苦於找不到原因。他們反復地檢查SQL的執行效率,提高機器的檔次,但效率的增加很少。

最根本的問題就出在這個演算法本身。演算法定了,能夠再優化的機會就不多了。我們下面來介紹一種演算法,效率將是上面演算法的10倍以上。

分類編碼演算法

問題就出在前面我們採用了順序編碼,這是一種最簡單的編碼方法。大家知道,簡單並不意味著效率。實際上,編碼科學是程序員必修的課程。下面,我們通過設計一種編碼演算法,使分類的編號ID中同時包含了其父類的信息。一個五級分類的例子如下:

此例中,用32(4+7+7+7+7)位整數來編碼,其中,第一級分類有4位,可以表達16種分類。第二級到第五級分類分別有7位,可以表達128個子分類。

顯然,如果我們得到一個編碼為 1092787200 的分類,我們就知道:由於其編碼為

0100 0001001 0001010 0111000 0000000

所以它是第四級分類。其父類的二進制編碼是0100 0001001 0001010 0000000 0000000,十進制編號為1092780032。依次我們還可以知道,其父類的父類編碼是0100 0001001 0000000 0000000 0000000,其父類的父類的父類編碼是0100 0000000 0000000 0000000 0000000。

現在我們在一般的情況下來討論類別編碼問題。設類別的層次為k,第i層的編碼位數為Ni, 那麼總的編碼位數為N(N1+N2+..+Nk)。我們就得到任何一個類別的編碼形式如下:

2^(N-(N1+N2+…+Ni))*j + 父類編碼

其中,i表示第i層,j表示當前層的第j個分類。這樣我們就把任何分類的編碼分成了兩個部分,其中一部分是它的層編碼,一部分是它的父類編碼。由下面公式定一的k個編碼我們稱為特徵碼:(因為i可以取k個值,所以有k個)

2^N-2^(N-(N1+N2+…+Ni))

對於任何給定的類別ID,如果我們把ID和k個特徵碼「相與」,得到的非0編碼,就是其所有父類的編碼!

位編碼演算法

對任何順序編碼的Catalog表,我們可以設計一個位編碼演算法,將所有的類別編碼規格化為位編碼。在具體實現時,我們先創建一個臨時表:

Create TempCatalog(

[OldID] [int] NOT NULL,

[NewID] [int] NOT NULL,

[OldFatherID] [int] NOT NULL,

[NewFatherID] [int] NOT NULL

);

在這個表中,我們保留所有原來的類別編號OldID和其父類編號OldFatherID,以及重新計算的滿足位編碼要求的相應編號NewID、NewFatherID。

程序如下:

<%

REM oConn---資料庫連接,已經打開

REM OldFather---原來的父類編號

REM NewFather---新的父類編號

REM N---編碼總位數

REM Ni--每一級的編碼位數數組

REM Level--當前的級數

sub FormatAllID(oConn,OldFather,NewFather,N,Nm,Ni byref,Level)

strSQL = "select CatalogID ,
FatherID from Catalog where FatherID=" & OldFather

set rsCatalog=oConn.Execute( strSQL )

j = 1

do while not rsCatalog.EOF

i = 2 ^(N - Nm) * j

if Level then i= i + NewFather

OldCatalog = rsCatalog("CatalogID")

NewCatalog = i

REM 寫入臨時表:

strSQL = "Insert into TempCatalog (OldCatalogID ,
NewCatalogID , OldFatherID , NewFatherID)"

strSQL = strSQL & " values(" & OldCatalog & " ,
" & NewCatalog & " , " & OldFather & " , " & NewFather & ")"

Conn.Execute strSQL

REM 遞歸調用FormatAllID:

Nm = Nm + Ni(Level+1)

FormatAllID oConn,OldCatalog , NewCatalog ,N,Nm,Ni,Level + 1

rsCatalog.MoveNext

j = j+1

loop

rsCatalog.Close

end sub

%>

調用這個演算法的一個例子如下:

<%

REM 定義編碼參數,其中N為總位數,Ni為每一級的位數。

Dim N,Ni(5)

Ni(1) = 4

N = Ni(1)

for i=2 to 5

Ni(i) = 7

N = N + Ni(i)

next

REM 打開資料庫,創建臨時表:

strSQL = "Create TempCatalog( [OldID]
[int] NOT NULL, [NewID] [int] NOT NULL,
[OldFatherID] [int] NOT NULL, [NewFatherID] [int] NOT NULL);"

Set Conn = Server.CreateObject("ADODB.Connection")

Conn.Open Application("strConn")

Conn.Execute strSQL

REM 調用規格化常式:

FormatAllID Conn,-1,-1,N,Ni(1),Ni,0

REM ---------------------------------------------

REM 在此處更新所有相關表的類別編碼為新的編碼即可。

REM ----------------------------------------------

REM 關閉資料庫:

strSQL= "drop table TempCatalog;"
Conn.Execute strSQL
Conn.Close

%>

第四個問題

現在我們回頭看看第四個問題:怎樣得到某個分類下的所有產品。由於採用了位編碼,現在問題變得很簡單。我們很容易推算:某個產品屬於某個類別的條件是Proct.FatherID&(Catalog.ID的特徵碼)=Catalog.ID。其中「&」代表位與演算法。這在SQL Server中是直接支持的。

舉例來說:產品所屬的類別為:1092787200,而當前類別為1092780032。當前類別對應的特徵值為:4294950912,由於1092787200&4294950912=8537400,所以這個產品屬於分類8537400。

我們前面已經給出了計算特徵碼的公式。特徵碼並不多,而且很容易計算,可以考慮在Global.asa中Application_OnStart時間觸發時計算出來,存放在Application(「Mark」)數組中。

當然,有了特徵碼,我們還可以得到更加有效率的演算法。我們知道,雖然我們採用了位編碼,實際上還是一種順序編碼的方法。表現出第I級的分類編碼肯定比第I+1級分類的編碼要小。根據這個特點,我們還可以由FID得到兩個特徵碼,其中一個是本級位特徵碼FID0,一個是上級位特徵碼FID1。而產品屬於某個分類FID的充分必要條件是:

Proct.FatherID>FID0 and Proct.FatherID<FID1

下面的程序顯示分類FID下的所有產品。由於數據表Proct已經對FatherID進行索引,故查詢速度極快:

<%

REM oConn---資料庫連接,已經打開

REM FID---當前分類

REM FIDMark---特徵值數組,典型的情況下為Application(「Mark」)

REM k---數組元素個數,也是分類的級數

Sub GetAllProct(oConn,FID,FIDMark byref,k)

' 根據FID計算出特徵值FID0,FID1

for i=k to 1

if (FID and FIDMark = FID ) then exit

next

strSQL = "select Name from Proct where FatherID>
"FIDMark(i)&" and FatherID<"FIDMark(i-1)

set rsProct=oConn.Execute(strSQL)%>

<UL><%

Do While Not rsProct.Eof%>

<LI><%=rsProct("Name")

Loop%>

</UL><%

rsProct.Close

End Sub

%>

關於第5個問題、第6個問題,就留作習題吧。有了上面的位編碼,一切都應該迎刃而解。

熱點內容
android動態載入布局 發布:2024-11-16 21:37:54 瀏覽:798
php判斷ip 發布:2024-11-16 21:07:03 瀏覽:738
有看頭密碼怎麼改 發布:2024-11-16 20:57:39 瀏覽:326
A有語法錯誤不能編譯 發布:2024-11-16 20:49:17 瀏覽:946
廚房需要配置什麼噴淋頭 發布:2024-11-16 20:39:02 瀏覽:298
酒瓶解壓 發布:2024-11-16 20:29:20 瀏覽:730
視頻怎樣上傳到手機 發布:2024-11-16 20:26:30 瀏覽:259
怎麼把ppt文件壓縮 發布:2024-11-16 20:22:30 瀏覽:686
linux大內存 發布:2024-11-16 20:22:28 瀏覽:951
屏蔽迅雷上傳 發布:2024-11-16 19:49:17 瀏覽:601