国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Adjacent List Model 與 Nested Set Model 兩種無線分類模型的對比

sshe / 2370人閱讀

摘要:相反,我們添加了一個第三自連接,以及一個子查詢以確定這個深度將作為子樹的新起點這個函數可以被運用到任何節點上,包括根節點。我們可以在之前的語句上添加一條語句來輕松實現如果想顯示父節點,將改為。

原文鏈接:http://www.pilishen.com/posts...

我們都曾在數據庫中處理過層級數據-這種數據中的每項都有一個父項和(0或多個)子項,根項除外。比如:論壇和郵件列表中的分類、商業組織結構表、內容管理系統的分類和產品分類等等。
在關系型數據庫中處理層級數據時我們總會覺得關系型數據庫不是為處理層級數據設計的,因為關系型數據庫的數據表不像XML具有層級,而是一個簡單的扁平化的表。所以層級數據的這種父-子關系不能在數據表中自然的展現出來。

下面我們介紹兩種在關系型數據庫中處理層級數據的模型:

Adjacent List Model 鄰接表模型

我們以下圖的電子產品分類為例

通常上面的產品分類會像下面這樣來設計表結構并被儲存:

CREATE TABLE category(
        category_id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(20) NOT NULL,
        parent INT DEFAULT NULL
);

INSERT INTO category VALUES(1,"ELECTRONICS",NULL),(2,"TELEVISIONS",1),(3,"TUBE",2),
        (4,"LCD",2),(5,"PLASMA",2),(6,"PORTABLE ELECTRONICS",1),(7,"MP3 PLAYERS",6),(8,"FLASH",7),
        (9,"CD PLAYERS",6),(10,"2 WAY RADIOS",6);

SELECT * FROM category ORDER BY category_id;
+-------------+----------------------+--------+
| category_id | name                 | parent |
+-------------+----------------------+--------+
|           1 | ELECTRONICS          |   NULL |
|           2 | TELEVISIONS          |      1 |
|           3 | TUBE                 |      2 |
|           4 | LCD                  |      2 |
|           5 | PLASMA               |      2 |
|           6 | PORTABLE ELECTRONICS |      1 |
|           7 | MP3 PLAYERS          |      6 |
|           8 | FLASH                |      7 |
|           9 | CD PLAYERS           |      6 |
|          10 | 2 WAY RADIOS         |      6 |
+-------------+----------------------+--------+
10 rows in set (0.00 sec)

在鄰接表模型中,表中的每條記錄都包含一個指向父項id的字段。根項也就是這里的electronics的父項id為null,這種表結構非常的簡單,而且我們很清楚的看到:flash的父項是MP3 , MP3的父項是protable electronics、protable electronics 的父項是electronics等等。雖然在客戶端編碼中鄰接表模型處理起來也相當的簡單,但是如果是純SQL編碼的話,該模型會有很多問題。

檢索整個樹

檢索整個樹是處理層級數據最常見的任務,為了完成這個最常用的方法是通過自連接(self-join):

SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4
FROM category AS t1
LEFT JOIN category AS t2 ON t2.parent = t1.category_id
LEFT JOIN category AS t3 ON t3.parent = t2.category_id
LEFT JOIN category AS t4 ON t4.parent = t3.category_id
WHERE t1.name = "ELECTRONICS";

+-------------+----------------------+--------------+-------+
| lev1        | lev2                 | lev3         | lev4  |
+-------------+----------------------+--------------+-------+
| ELECTRONICS | TELEVISIONS          | TUBE         | NULL  |
| ELECTRONICS | TELEVISIONS          | LCD          | NULL  |
| ELECTRONICS | TELEVISIONS          | PLASMA       | NULL  |
| ELECTRONICS | PORTABLE ELECTRONICS | MP3 PLAYERS  | FLASH |
| ELECTRONICS | PORTABLE ELECTRONICS | CD PLAYERS   | NULL  |
| ELECTRONICS | PORTABLE ELECTRONICS | 2 WAY RADIOS | NULL  |
+-------------+----------------------+--------------+-------+
6 rows in set (0.00 sec)
檢索所有的葉子節點

我們可以通過左連接(left-join)檢索出所有的葉子節點(沒有子節點的節點):

SELECT t1.name FROM
category AS t1 LEFT JOIN category as t2
ON t1.category_id = t2.parent
WHERE t2.category_id IS NULL;

+--------------+
| name         |
+--------------+
| TUBE         |
| LCD          |
| PLASMA       |
| FLASH        |
| CD PLAYERS   |
| 2 WAY RADIOS |
+--------------+
檢索一條路徑

自連接同樣可以讓我檢索出層級結構中的一條完整的層級路徑

SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4
FROM category AS t1
LEFT JOIN category AS t2 ON t2.parent = t1.category_id
LEFT JOIN category AS t3 ON t3.parent = t2.category_id
LEFT JOIN category AS t4 ON t4.parent = t3.category_id
WHERE t1.name = "ELECTRONICS" AND t4.name = "FLASH";

+-------------+----------------------+-------------+-------+
| lev1        | lev2                 | lev3        | lev4  |
+-------------+----------------------+-------------+-------+
| ELECTRONICS | PORTABLE ELECTRONICS | MP3 PLAYERS | FLASH |
+-------------+----------------------+-------------+-------+
1 row in set (0.01 sec)

這個方法的主要局限性在于對于層級結構中的每一層都要自連接,并且隨著層級的增加這種自連接將變的越來越復雜也就自然的影響著性能。

鄰接表模型的局限性

在純SQL中使用鄰接表模型會很困難,如果想檢索某個分類在層級結構中的路徑就需要事先知道它在層級結構中所處的層級,此外當進行刪除某項操作時需要非常小心,因為在刪除的過程中可能會導致出現整個的孤立的子樹(刪除portable electronics 會使它下面所有的子項變孤立)。其中一些局限可以通過使用客戶端編碼或Stored Procedure(存儲過程是一組為了完成特定功能的SQL語句集,經編譯后存儲在數據庫中,用戶通過指定存儲過程的名字并給定參數來調用執行它)來解決。使用面向過程的語言,我們可以從樹的底部開始,向上迭代返回完整的樹或一條路徑。我們也可以通過提升子項和對剩下的子項重新排序以使之指向新的父項來避免產生孤立的子樹。

The Nested Set Model 嵌套集合模型

本篇文章將聚焦于嵌套集合模型,在這種模型中我們可以以一種新的方式來看待我們的層級數據,不是以節點和節點之間的線,而是以一種嵌套容器的方式,試著以下面的方式來展示我們的電器分類:

注意我們是怎么實現層級結構的,父項包含它們所有的子節點。我們通過使用左值和右值來在數據表上表示這種形式的層級結構,以此表示項目的嵌套關系

CREATE TABLE nested_category (
        category_id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(20) NOT NULL,
        lft INT NOT NULL,
        rgt INT NOT NULL
);

INSERT INTO nested_category VALUES(1,"ELECTRONICS",1,20),(2,"TELEVISIONS",2,9),(3,"TUBE",3,4),
 (4,"LCD",5,6),(5,"PLASMA",7,8),(6,"PORTABLE ELECTRONICS",10,19),(7,"MP3 PLAYERS",11,14),(8,"FLASH",12,13),
 (9,"CD PLAYERS",15,16),(10,"2 WAY RADIOS",17,18);

SELECT * FROM nested_category ORDER BY category_id;

+-------------+----------------------+-----+-----+
| category_id | name                 | lft | rgt |
+-------------+----------------------+-----+-----+
|           1 | ELECTRONICS          |   1 |  20 |
|           2 | TELEVISIONS          |   2 |   9 |
|           3 | TUBE                 |   3 |   4 |
|           4 | LCD                  |   5 |   6 |
|           5 | PLASMA               |   7 |   8 |
|           6 | PORTABLE ELECTRONICS |  10 |  19 |
|           7 | MP3 PLAYERS          |  11 |  14 |
|           8 | FLASH                |  12 |  13 |
|           9 | CD PLAYERS           |  15 |  16 |
|          10 | 2 WAY RADIOS         |  17 |  18 |
+-------------+----------------------+-----+-----+

我們使用lft和rgt來表示左值和右值,然而我們怎么確定這兩個值呢?我們從外出節點最左邊向右邊編號:

這種設計也可以運用在經典樹上:

檢索整個樹

由于一個節點的左值永遠在其父節點的左值和右值之間,所以我們可以通過自連接來檢索一整個樹:

SELECT node.name
FROM nested_category AS node,
        nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
        AND parent.name = "ELECTRONICS"
ORDER BY node.lft;

+----------------------+
| name                 |
+----------------------+
| ELECTRONICS          |
| TELEVISIONS          |
| TUBE                 |
| LCD                  |
| PLASMA               |
| PORTABLE ELECTRONICS |
| MP3 PLAYERS          |
| FLASH                |
| CD PLAYERS           |
| 2 WAY RADIOS         |
+----------------------+

不想上面鄰接表模型中的例子,這種查詢不需要知道樹的深度,我們也不需要在意是否需要在BETWEEN語句中加上節點右值的判斷語句,因為右值總是與左值處于相同的父項下。

檢索所有的葉子節點

在嵌套集合模型中檢索葉子節點也比在鄰接表模型中使用左連接方法要簡單得多。如果你仔細觀察nested_category表,你會發現所有的葉子節點的左值與右值是兩個連續的數字,所有為了檢索葉子節點,我們只需要檢索那些rgt = lft +1 的節點就行了:

SELECT name
FROM nested_category
WHERE rgt = lft + 1;

+--------------+
| name         |
+--------------+
| TUBE         |
| LCD          |
| PLASMA       |
| FLASH        |
| CD PLAYERS   |
| 2 WAY RADIOS |
+--------------+
檢索一條路徑

使用嵌套集合模型,我們可以檢索一條路徑而不需要之前那樣復雜的多次自連接:

SELECT parent.name
FROM nested_category AS node,
        nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
        AND node.name = "FLASH"
ORDER BY parent.lft;

+----------------------+
| name                 |
+----------------------+
| ELECTRONICS          |
| PORTABLE ELECTRONICS |
| MP3 PLAYERS          |
| FLASH                |
+----------------------+
檢索節點的深度

我們已經了解了怎么檢索整個樹,但是如果我們還需要知道樹中的每個節點的深度,以便更好的確定層級結構中的各個節點到底處于什么位置怎么辦呢? 我們可以通過增加COUNT函數和一條GROUP BY 語句到我們已存在的查詢語句中來實現顯示整個樹:

SELECT node.name, (COUNT(parent.name) - 1) AS depth
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;

+----------------------+-------+
| name                 | depth |
+----------------------+-------+
| ELECTRONICS          |     0 |
| TELEVISIONS          |     1 |
| TUBE                 |     2 |
| LCD                  |     2 |
| PLASMA               |     2 |
| PORTABLE ELECTRONICS |     1 |
| MP3 PLAYERS          |     2 |
| FLASH                |     3 |
| CD PLAYERS           |     2 |
| 2 WAY RADIOS         |     2 |
+----------------------+-------+

我們可以使用CONCAT和REPEAT字符串函數來根據深度縮進分類名稱:

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;

+-----------------------+
| name                  |
+-----------------------+
| ELECTRONICS           |
|  TELEVISIONS          |
|   TUBE                |
|   LCD                 |
|   PLASMA              |
|  PORTABLE ELECTRONICS |
|   MP3 PLAYERS         |
|    FLASH              |
|   CD PLAYERS          |
|   2 WAY RADIOS        |
+-----------------------+

當然,你可以利用深度值直接在客戶端應用程序上展現層級結構。Web開發者可以遍歷樹,并根據深度值的變化增加

    • 標簽。

      子樹深度

      當我們需要子樹的深度信息時,我們不能在自連接中限制節點或父表,因為它會破壞我們的結果。相反,我們添加了一個第三自連接,以及一個子查詢以確定這個深度將作為子樹的新起點:

      SELECT node.name, (COUNT(parent.name) - (sub_tree.depth + 1)) AS depth
      FROM nested_category AS node,
              nested_category AS parent,
              nested_category AS sub_parent,
              (
                      SELECT node.name, (COUNT(parent.name) - 1) AS depth
                      FROM nested_category AS node,
                      nested_category AS parent
                      WHERE node.lft BETWEEN parent.lft AND parent.rgt
                      AND node.name = "PORTABLE ELECTRONICS"
                      GROUP BY node.name
                      ORDER BY node.lft
              )AS sub_tree
      WHERE node.lft BETWEEN parent.lft AND parent.rgt
              AND node.lft BETWEEN sub_parent.lft AND sub_parent.rgt
              AND sub_parent.name = sub_tree.name
      GROUP BY node.name
      ORDER BY node.lft;
      
      +----------------------+-------+
      | name                 | depth |
      +----------------------+-------+
      | PORTABLE ELECTRONICS |     0 |
      | MP3 PLAYERS          |     1 |
      | FLASH                |     2 |
      | CD PLAYERS           |     1 |
      | 2 WAY RADIOS         |     1 |
      +----------------------+-------+

      這個函數可以被運用到任何節點上,包括根節點。查詢的深度值總是相對應該指定節點。

      查找節點的直接后代

      假設你正在一個零售網站上展示電子產品分類。當一個用戶點擊一個分類后,你想要顯示那個分類下面的產品并列出它們的子分類,而不是它們下面的完整分類樹,為了達到目的,我們需要顯示它的直接子節點。但是不向下更進一步檢索。例如:我們顯示PORTABLE ELECTRONICS 分類,我們想顯示P3 PLAYERS, CD PLAYERS, 和2 WAY RADIOS,但是不想顯示FLASH。

      我們可以在之前的語句上添加一條HABING語句來輕松實現:

      SELECT node.name, (COUNT(parent.name) - (sub_tree.depth + 1)) AS depth
      FROM nested_category AS node,
              nested_category AS parent,
              nested_category AS sub_parent,
              (
                      SELECT node.name, (COUNT(parent.name) - 1) AS depth
                      FROM nested_category AS node,
                              nested_category AS parent
                      WHERE node.lft BETWEEN parent.lft AND parent.rgt
                              AND node.name = "PORTABLE ELECTRONICS"
                      GROUP BY node.name
                      ORDER BY node.lft
              )AS sub_tree
      WHERE node.lft BETWEEN parent.lft AND parent.rgt
              AND node.lft BETWEEN sub_parent.lft AND sub_parent.rgt
              AND sub_parent.name = sub_tree.name
      GROUP BY node.name
      HAVING depth <= 1
      ORDER BY node.lft;
      
      +----------------------+-------+
      | name                 | depth |
      +----------------------+-------+
      | PORTABLE ELECTRONICS |     0 |
      | MP3 PLAYERS          |     1 |
      | CD PLAYERS           |     1 |
      | 2 WAY RADIOS         |     1 |
      +----------------------+-------+

      如果想顯示父節點,將HAVING depth <= 1改為HAVING depth = 1

      嵌套集合中的聚合函數

      讓我們添加一個產品表來演示聚合函數:

      CREATE TABLE product
      (
              product_id INT AUTO_INCREMENT PRIMARY KEY,
              name VARCHAR(40),
              category_id INT NOT NULL
      );
      
      INSERT INTO product(name, category_id) VALUES("20" TV",3),("36" TV",3),
      ("Super-LCD 42"",4),("Ultra-Plasma 62"",5),("Value Plasma 38"",5),
      ("Power-MP3 5gb",7),("Super-Player 1gb",8),("Porta CD",9),("CD To go!",9),
      ("Family Talk 360",10);
      
      SELECT * FROM product;
      
      +------------+-------------------+-------------+
      | product_id | name              | category_id |
      +------------+-------------------+-------------+
      |          1 | 20" TV            |           3 |
      |          2 | 36" TV            |           3 |
      |          3 | Super-LCD 42"     |           4 |
      |          4 | Ultra-Plasma 62"  |           5 |
      |          5 | Value Plasma 38"  |           5 |
      |          6 | Power-MP3 128mb   |           7 |
      |          7 | Super-Shuffle 1gb |           8 |
      |          8 | Porta CD          |           9 |
      |          9 | CD To go!         |           9 |
      |         10 | Family Talk 360   |          10 |
      +------------+-------------------+-------------+

      現在讓我們來寫一套查詢語句來檢索帶有各分類產品數量的分類樹:

      SELECT parent.name, COUNT(product.name)
      FROM nested_category AS node ,
              nested_category AS parent,
              product
      WHERE node.lft BETWEEN parent.lft AND parent.rgt
              AND node.category_id = product.category_id
      GROUP BY parent.name
      ORDER BY node.lft;
      
      +----------------------+---------------------+
      | name                 | COUNT(product.name) |
      +----------------------+---------------------+
      | ELECTRONICS          |                  10 |
      | TELEVISIONS          |                   5 |
      | TUBE                 |                   2 |
      | LCD                  |                   1 |
      | PLASMA               |                   2 |
      | PORTABLE ELECTRONICS |                   5 |
      | MP3 PLAYERS          |                   2 |
      | FLASH                |                   1 |
      | CD PLAYERS           |                   2 |
      | 2 WAY RADIOS         |                   1 |
      +----------------------+---------------------+

      這是我們典型的整樹查詢語句,包含一個COUNT函數和GROUP BY 函數,以及產品表的引用和在WHERE語句中對node和product表的關聯。就像你看到的,每個分類都計數,子分類的產品數量在父分類上反應出來

      添加新的節點

      既然我們以及學會了怎么檢索我們的樹,接下來我們來了解下怎么添加新的節點到我們的樹中,我們再來看看下面的圖表:

      如果我想在TELEVISIONS 和PORTABLE ELECTRONICS 中間添加新的節點,那么這個新的節點將會給予lft 和 rgt 分別為10和11(我們是從左向右編號的),它右邊所有的節點的lft和rgt值都將加2,這些可以使用MySql儲存過程解決:

      LOCK TABLE nested_category WRITE;
      
      SELECT @myRight := rgt FROM nested_category
      WHERE name = "TELEVISIONS";
      
      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("GAME CONSOLES", @myRight + 1, @myRight + 2);
      
      UNLOCK TABLES;

      We can then check our nesting with our indented tree query:

      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;
      
      +-----------------------+
      | name                  |
      +-----------------------+
      | ELECTRONICS           |
      |  TELEVISIONS          |
      |   TUBE                |
      |   LCD                 |
      |   PLASMA              |
      |  GAME CONSOLES        |
      |  PORTABLE ELECTRONICS |
      |   MP3 PLAYERS         |
      |    FLASH              |
      |   CD PLAYERS          |
      |   2 WAY RADIOS        |
      +-----------------------+

      如果我們想給一個沒有子節點的節點添加一個子節點,我們需要稍微改改我們的語句。讓我們在 2 WAY RADIOS節點下面添加新的FRS節點:

      LOCK TABLE nested_category WRITE;
      
      SELECT @myLeft := lft FROM nested_category
      
      WHERE name = "2 WAY RADIOS";
      
      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("FRS", @myLeft + 1, @myLeft + 2);
      
      UNLOCK TABLES;

      在這個例子中我們將我們新的父節點的左值右邊的值全部擴大。然后將改節點插入到父節點左值的右邊:

      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;
      
      +-----------------------+
      | name                  |
      +-----------------------+
      | ELECTRONICS           |
      |  TELEVISIONS          |
      |   TUBE                |
      |   LCD                 |
      |   PLASMA              |
      |  GAME CONSOLES        |
      |  PORTABLE ELECTRONICS |
      |   MP3 PLAYERS         |
      |    FLASH              |
      |   CD PLAYERS          |
      |   2 WAY RADIOS        |
      |    FRS                |
      +-----------------------+
      刪除節點

      最后我們了解下移除節點。刪除節點時所采取的操作過程取決于節點在層級結構中的位置;刪除葉節點比刪除帶有子節點的節點要容易得多,因為我們必須處理孤立的節點
      刪除葉子節點的過程與添加新的節點正好相反,我們刪除該節點并且刪除父節點中它的寬度:

      LOCK TABLE nested_category WRITE;
      
      SELECT @myLeft := lft, @myRight := rgt, @myWidth := rgt - lft + 1
      FROM nested_category
      WHERE name = "GAME CONSOLES";
      
      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;

      我們再次執行我們上面的縮進樹的查詢語句來確認我們刪除了節點且沒有破壞層級結構:

      
      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;
      
      +-----------------------+
      | name                  |
      +-----------------------+
      | ELECTRONICS           |
      |  TELEVISIONS          |
      |   TUBE                |
      |   LCD                 |
      |   PLASMA              |
      |  PORTABLE ELECTRONICS |
      |   MP3 PLAYERS         |
      |    FLASH              |
      |   CD PLAYERS          |
      |   2 WAY RADIOS        |
      |    FRS                |
      +-----------------------+

      這個方法對刪除節點和它的子節點同樣有效:

      LOCK TABLE nested_category WRITE;
      
      SELECT @myLeft := lft, @myRight := rgt, @myWidth := rgt - lft + 1
      FROM nested_category
      WHERE name = "MP3 PLAYERS";
      
      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;

      我們再次查詢以驗證我們成功的刪除了整個子樹:

      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;
      
      +-----------------------+
      | name                  |
      +-----------------------+
      | ELECTRONICS           |
      |  TELEVISIONS          |
      |   TUBE                |
      |   LCD                 |
      |   PLASMA              |
      |  PORTABLE ELECTRONICS |
      |   CD PLAYERS          |
      |   2 WAY RADIOS        |
      |    FRS                |
      +-----------------------+

      另一個場景是我們需要刪除父節點,但是需要保留它的子節點。有時你可能會僅僅是將它的名稱改為一個占位符直到新的名稱來替換它,有時這些子節點需要提升到被刪除的父節點的層級:

      LOCK TABLE nested_category WRITE;
      
      SELECT @myLeft := lft, @myRight := rgt, @myWidth := rgt - lft + 1
      FROM nested_category
      WHERE name = "PORTABLE ELECTRONICS";
      
      DELETE FROM nested_category WHERE lft = @myLeft;
      
      UPDATE nested_category SET rgt = rgt - 1, lft = lft - 1 WHERE lft BETWEEN @myLeft AND @myRight;
      UPDATE nested_category SET rgt = rgt - 2 WHERE rgt > @myRight;
      UPDATE nested_category SET lft = lft - 2 WHERE lft > @myRight;
      
      UNLOCK TABLES;

      這里我們改節點右側的節點的左右值全部減去2,該節點的所有子節點的左右值全部減去1,我們再次來驗證下這些元素有沒有被提升:

      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;
      
      +---------------+
      | name          |
      +---------------+
      | ELECTRONICS   |
      |  TELEVISIONS  |
      |   TUBE        |
      |   LCD         |
      |   PLASMA      |
      |  CD PLAYERS   |
      |  2 WAY RADIOS |
      |   FRS         |
      +---------------+
      總結

      相對于鄰接表模型,嵌套集合模型在層級數據的查詢中具有極大的優勢,而在數據的插入和刪除操作時則根據插入或刪除數據的位置的不同,可能需要更新很多節點甚至是整個樹的左右值,從而影響數據庫的性能。對于客戶端需要頻繁修改表的程序我們應該避免使用嵌套集合模型,而對于客戶端需要頻繁的查詢表的程序我們應當使用它,像商城的產品分類表,表的數據只是在后臺維護,而大量的用戶會產生大量的查詢。

      文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

      轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/28170.html

      相關文章

      • 嵌套集合模型(Nested set model)介紹

        摘要:原文鏈接歡迎作客我們的學習群本文翻譯自維基百科嵌套集合模型是一種在關系型數據庫中表示嵌套集合的特殊技術。誘因該技術的出現解決了標準關系代數和關系演算以及基于它們的操作不能直接在層次結構上表示所有期望操作的問題。這通常被稱為物料清單問題。 原文鏈接:http://www.pilishen.com/posts...; 歡迎作客我們的php&Laravel學習群:109256050本文翻譯自...

        Half 評論0 收藏0
      • Flask Api 文檔管理 Swagger 上手

        摘要:眾數周知,文檔的編寫和整理工作將花費巨大精力甚至不亞于代碼的編寫,因此在時間緊任務重的情況下,文檔是首先被忽略的工作。是一款非常流行的文檔管理交互工具,適用于在團隊中的管理,以及服務組件對接。而我們目前需要的是獲取文檔或文件。 本文最先發布在博客:https://blog.ihypo.net/152551... Flask 是一個以自由度高、靈活性強著稱的 Python Web 框架...

        Scholer 評論0 收藏0
      • laravel-nestedset:多級無限分類正確姿勢

        摘要:通過自定義的查詢加載和大多數情況下,你需要按層級排序祖先集合可以被預加載視圖模板中面包屑將祖先的全部取出后轉換為數組,在用拼接為字符串輸出。 原文鏈接:http://www.pilishen.com/posts...; 歡迎作客我們的php&Laravel學習群:109256050 laravel-nestedset是一個關系型數據庫遍歷樹的larvel4-5的插件包 目錄: Nes...

        pf_miles 評論0 收藏0
      • 如何實現一個基本微信文章分類

        摘要:本文源地址,轉發請注明該地址或地址,謝謝微信公眾號發布的文章和一般門戶網站的新聞文本類型有所不同,通常不能用現有的文本分類器直接對這些文章進行分類,不過文本分類的原理是相通的,本文以微信公眾號文章為對象,介紹樸素貝葉斯分類器的實現過程。 本文源地址:http://www.fullstackyang.com/...,轉發請注明該地址或segmentfault地址,謝謝! 微信公眾號發布的...

        dackel 評論0 收藏0

      發表評論

      0條評論

      最新活動
      閱讀需要支付1元查看
      <