0% found this document useful (0 votes)
55 views33 pages

Managing Hierarchical Data in Mysql: Mike Hillyer - Mysql Ab

Uploaded by

sleyter94
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
55 views33 pages

Managing Hierarchical Data in Mysql: Mike Hillyer - Mysql Ab

Uploaded by

sleyter94
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 33

200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.

com 1

Managing Hierarchical Data


in MySQL

Mike Hillyer - MySQL AB


200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 2

About Me
Mike Hillyer, BSc

• Member of the MySQL AB Documentation Team


• MySQL Core and Pro Certified
• MySQL Expert at www.experts-exchange.com
• Resident MySQL Expert at SearchDatabase.com
• http://www.openwin.org/mike/aboutme.php
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 3

About You
How many of you…

• Currently use MySQL?


• Another RDBMS?
• Manage hierarchical data?
• Will be managing hierarchical data?
• Know what hierarchical data is?
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 4

About This Session

• http://www.openwin.org/mike/index.php/presentations/
• http://dev.mysql.com/tech-resources/articles/hierarchical-data.html

• What is hierarchical data?


• The Adjacency List Model
• The Nested Set Model
• Querying the Nested Set Model
– Adding New Nodes
– Deleting Nodes
– Additional Resources
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 5

What is Hierarchical Data?

• Data that maintains a parent-child relationship


• Nodes have zero or one parent, zero to many children
• Only the root node has no parent
• Various types of data
– Mailing list/forum threads
– Organizational charts
– Content management categories
– Product categories
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 6

Product Categories
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 7

The Adjacency List Model


+-------------+----------------------+--------+
| 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 |
+-------------+----------------------+--------+
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 8

Full Tree
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)
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 9

Leaf Nodes
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 |
+--------------+
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 10

Single Path
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)
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 11

Limitations of Adjacency Lists

• Adjacency list model not normalized.


• Deleting nodes can orphan children.
• Querying paths and trees requires multiple self-joins.
• Procedural code required for most use-cases.
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 12

Nested Sets
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 13

Nested Set Table

+-------------+----------------------+-----+-----+
| 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 |
+-------------+----------------------+-----+-----+
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 14

Numbered Sets
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 15

Numbered Tree
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 16

Full Tree
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 |
+----------------------+
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 17

Leaf Nodes
SELECT name
FROM nested_category
WHERE rgt = lft + 1;

+--------------+
| name |
+--------------+
| TUBE |
| LCD |
| PLASMA |
| FLASH |
| CD PLAYERS |
| 2 WAY RADIOS |
+--------------+
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 18

Node Depth
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 |
+----------------------+-------+
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 19

Indented Nodes
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 |
+-----------------------+
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 20

Depth of a Sub-Tree
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;
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 21

Depth of a Sub-Tree - II

+----------------------+-------+
| name | depth |
+----------------------+-------+
| PORTABLE ELECTRONICS | 0 |
| MP3 PLAYERS | 1 |
| FLASH | 2 |
| CD PLAYERS | 1 |
| 2 WAY RADIOS | 1 |
+----------------------+-------+
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 22

Immediate Subordinates
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 |
+----------------------+-------+
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 23

Aggregate Functions
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 |
+------------+-------------------+-------------+
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 24

Aggregate Functions - II
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 |
+----------------------+---------------------+
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 25

Adding Nodes
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 26

Adding a Sibling
LOCK TABLE nested_category WRITE; +-----------------------+
| name |
+-----------------------+
SELECT @myRight := rgt | ELECTRONICS |
FROM nested_category | TELEVISIONS |
WHERE name = 'TELEVISIONS'; | TUBE |
| LCD |
UPDATE nested_category | PLASMA |
SET rgt = rgt + 2 | GAME CONSOLES |
WHERE rgt > @myRight; | PORTABLE ELECTRONICS |
| MP3 PLAYERS |
| FLASH |
UPDATE nested_category | CD PLAYERS |
SET lft = lft + 2 | 2 WAY RADIOS |
WHERE lft > @myRight; +-----------------------+

INSERT INTO nested_category(name, lft, rgt)


VALUES('GAME CONSOLES', @myRight + 1, @myRight + 2);

UNLOCK TABLES;
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 27

Adding a Child
LOCK TABLE nested_category WRITE; +-----------------------+
| name |
SELECT @myLeft := lft +-----------------------+
| ELECTRONICS |
FROM nested_category | TELEVISIONS |
WHERE name = '2 WAY RADIOS'; | TUBE |
| LCD |
| PLASMA |
UPDATE nested_category | GAME CONSOLES |
SET rgt = rgt + 2 | PORTABLE ELECTRONICS |
WHERE rgt > @myLeft; | MP3 PLAYERS |
| FLASH |
| CD PLAYERS |
UPDATE nested_category | 2 WAY RADIOS |
SET lft = lft + 2 | FRS |
WHERE lft > @myLeft; +-----------------------+

INSERT INTO nested_category(name, lft, rgt)


VALUES('FRS', @myLeft + 1, @myLeft + 2);

UNLOCK TABLES;
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 28

Deleting a Leaf Node


LOCK TABLE nested_category WRITE;

SELECT @myLeft := lft, @myRight := rgt, @myWidth := rgt -


lft + 1
FROM nested_category +-----------------------+
| name |
WHERE name = 'GAME CONSOLES'; +-----------------------+
| ELECTRONICS |
DELETE FROM nested_category | TELEVISIONS |
WHERE lft BETWEEN @myLeft AND @myRight; | TUBE |
| LCD |
| PLASMA |
UPDATE nested_category | PORTABLE ELECTRONICS |
SET rgt = rgt - @myWidth | MP3 PLAYERS |
| FLASH |
WHERE rgt > @myRight; | CD PLAYERS |
| 2 WAY RADIOS |
UPDATE nested_category | FRS |
SET lft = lft - @myWidth +-----------------------+
WHERE lft > @myRight;

UNLOCK TABLES;
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 29

Deleting a Parent and all Children


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 | name |
WHERE lft BETWEEN @myLeft AND @myRight; +-----------------------+
| ELECTRONICS |
UPDATE nested_category | TELEVISIONS |
SET rgt = rgt - @myWidth | TUBE |
WHERE rgt > @myRight; | LCD |
| PLASMA |
UPDATE nested_category
SET lft = lft - @myWidth | PORTABLE ELECTRONICS |
WHERE lft > @myRight; | CD PLAYERS |
| 2 WAY RADIOS |
UNLOCK TABLES; | FRS |
+-----------------------+
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 30

Deleting a Parent and


Promoting all Children
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;


+---------------+
| name |
UPDATE nested_category +---------------+
SET rgt = rgt - 1, lft = lft - 1
WHERE lft BETWEEN @myLeft AND @myRight; | ELECTRONICS |
| TELEVISIONS |
UPDATE nested_category
SET rgt = rgt - 2 | TUBE |
WHERE rgt > @myRight; | LCD |
UPDATE nested_category
| PLASMA |
SET lft = lft - 2 | CD PLAYERS |
WHERE lft > @myRight; | 2 WAY RADIOS |
UNLOCK TABLES;
| FRS |
+---------------+
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 31

Advanced Use Cases

• Move an entire sub-tree


• Handle high insert/delete volumes
– Calculate gaps
– Use floats
– See the resources next slide
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 32

Credit & Resources

Joe Celko's Trees and


Hierarchies in SQL for
Smarties
http://www.openwin.org/mike/index.php/books/
http://dev.mysql.com/tech-resources/articles/hierarchical-data.html
http://www.sitepoint.com/article/hierarchical-data-database
http://www.dbmsmag.com/9603d06.html
http://www.dbmsmag.com/9604d06.html
http://www.dbmsmag.com/9605d06.html
http://www.intelligententerprise.com/001020/celko.jhtml
http://searchdatabase.techtarget.com/tip/1,289483,sid13_gci537290,00.html
http://searchdatabase.techtarget.com/tip/1,289483,sid13_gci801943,00.html
http://www.klempert.de/php/nested_sets_demo
http://dev.e-taller.net/dbtree/
http://www.dbazine.com/oracle/or-articles/tropashko4
200603-08 | Managing Hierarchical Data | © MySQL AB 2005 | www.mysql.com 33

Conclusion

• http://www.openwin.org/mike/presentations/
• Questions?

You might also like