自定義排序之數據庫設計

自定義排序之數據庫設計

之前做過的項目有項需求,就是要對一個普通的列表進行自定義排序功能,當初構思了幾個方案,各有所長,按需使用,下面就一一來介紹這幾個方案。
注:這裏的自定義排序就是操作列表的某項進行位置交換。

1. 單表單列結構(數組結構)

 此設計是使用一個表中的一列來表示數據的序號,通常我們使用的方法就是這種。

數據表tb_data(n):

data index
··· 0
··· 1
··· 2

這裏規定序號從0開始遞增。

其基本數據操作如下:

  • 增 → 當增加一個數據時,定義data的序號爲數據總數量值。
  • 刪 → 當刪除一個數據時,將大於該序號的數據的序號都減1。
  • 改 → 當修改位置將數據a從x移動到y時,若x小於y,則將(x,y]範圍內的數據序號都減1;若x大於y,則將[y,x)範圍內的數據序號都加1(注:修改數據庫時,要先將a的序號x修改爲未被使用的序號z,然後再修改範圍內的數據,最後再將z修改爲y,順序不能亂)。
  • 查 → 當查找數據時添加 order by index 即可得到自定義排列的數據,查找第n個數據時查找條件爲 index=n-1 即可。

總結:此方法查找速度最快,修改速度最慢。

2.單表雙列結構(鏈表結構)

 此設計是使用一個表中的兩列來表示數據的序號,一列表示該數據的前置id,一列表示該數據的後置序id(id爲數據表本身的自增序號),即相當於我們經常使用的雙向鏈表。

數據表tb_data(n):

id data pre_no next_no
0 ··· -1 1
1 ··· 0 2
2 ··· 1 3
3 ··· 2 -1

這裏規定第一個數據的pre_no爲-1,最後一個數據的next_no爲-1。

其基本數據操作如下:

  • 增 → 當增加一個數據a時,先查找出最後一個數據b的id號,a的pre_no定義爲b的id號(若此數據爲第一個則定義爲-1),next_no定義爲-1,再將b的next_no定義爲a的id號。
  • 刪 → 當刪除一個數據a時,取出a的pre_no和next_no,將pre_no對應的id的數據的next_no修改爲a的next_no,將next_no對應的id的數據的pre_no修改爲a的pre_no。
  • 改 → 令位置x-1、x+1數據分別爲b、c,位置y-1、y、y+1的數據分別爲d、e、f,現修改位置將數據a從x移動到y時,
    當x小於y時,修改b的next_no爲c的id,修改c的pre_no爲b的id,修改e的next_no爲a的id,修改f的pre_no爲a的id,最後修改a的pre_no爲e的id,next_no爲f的id;
    當x大於y時,修改b的next_no爲c的id,修改c的pre_no爲b的id,修改d的next_no爲a的id,修改e的pre_no爲a的id,最後修改a的pre_no爲d的id,next_no爲e的id。
  • 查 → 當查找第n個數據時,需要先查找出第一個數據,在根據第一個數據逐個往後查找數據的next_no,查找n次後得到第n個數據。

總結:此方法查找速度最慢,修改速度最快。

3.雙表雙列結構(分頁結構)

此設計是使用一個頁碼錶記錄全部頁碼和頁碼的序號範圍,另一個數據表來記錄基本數據、自身序號和頁碼,通過在一個表中給數據設置不同的序號和頁碼來達到分頁排序的效果。

頁碼錶tb_page:

tb_name page start_index end_index
tb_data0 0 1 1000
tb_data0 1 1 1000
tb_data0 2 1 120
tb_data1 0 1 1000
tb_data1 1 1 130

table_name爲一個基本數據表的表名,對於每一個table_name,其對應的page都從0開始遞增且不能重複,每個page有一定的數據範圍(這裏設定爲一頁有1000條數據),則每個數據表對應的數據總量即可計算出來。

基本數據表tb_data(n):

data page index
··· 0 1
··· 0 ···
··· 0 1000
··· 1 1
··· 1 ···
··· 1 1000
··· 2 1
··· 2 ···
··· 2 120

data爲數據域,記錄基本數據,對於每一個不相同的data都有對應的page和index,通過page、index和每一頁的數據範圍即可計算出對應的全局序號。

其基本數據操作如下:

  • 增 → 當增加一個數據時,先從頁碼錶中查找出最後的page及其對應的start_index和end_index,若end_index-start_index+1沒有數據超出範圍,則插入數據的page不變,index爲end_index+1,若超出範圍,則需在頁碼錶中新建一頁,插入數據的page自加一,index賦值初始值。
  • 刪 → 當刪除一個數據時,因爲需要保證除末頁以外的頁碼的數據範圍都爲規定值,所以需要對刪除數據對應的頁碼及以上頁碼的數據進行調整,對於刪除數據的頁碼,可以通過對比該數據在頁碼中的相對位置來調整較小數據量的一方數據執行加減1,對於大於其的頁碼,可以將每一頁的首數據調整爲上一頁的末數據(末頁數量爲0即可將末頁刪除)。
  • 改 → 當修改位置將數據a從x移動到y,計算x、y對應的頁碼,當x、y的頁碼相同時,只需調整該頁數據,可通過對比x到y的數量和頁碼數量來決定調整x、y範圍內還是範圍外的數據信息;當x、y頁碼不同時,可通過對x、y在頁碼中的相對位置來調整較小數據量的一方數據執行加減1,若x小於y,(x,y]範圍內的頁的首數據調整爲上一頁的末數據,若x大於y,[y,x)範圍內的頁的末數據調整爲下一頁的首數據。
  • 查 → 當查找數據總量時,可以通過查找頁碼錶計算得出;當查找序號爲n的數據時,可以通過頁碼錶計算得到對應的page和index,然後再通過查找數據表取得數據(由於頁碼錶的數據會經常使用,所以最好從數據庫取出一次後保存在內存中再進行使用即可提高速度)。

總結:此方法查找速度和修改速度比較均衡,適合大多數情況使用。

PS:本人比較懶,代碼什麼的就沒有了…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章