<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Pure Performance Inc &#187; Materialized Path Model</title>
	<atom:link href="http://www.pure-performance.com/tag/materialized-path-model/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.pure-performance.com</link>
	<description>Web and PeopleSoft Consulting</description>
	<lastBuildDate>Fri, 02 Apr 2010 01:59:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Managing Hierarchical Data in SQL</title>
		<link>http://www.pure-performance.com/2009/03/managing-hierarchical-data-in-sql/</link>
		<comments>http://www.pure-performance.com/2009/03/managing-hierarchical-data-in-sql/#comments</comments>
		<pubDate>Fri, 13 Mar 2009 17:29:42 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[Adjacency List Model]]></category>
		<category><![CDATA[Celko]]></category>
		<category><![CDATA[connect_by]]></category>
		<category><![CDATA[Materialized Path Model]]></category>
		<category><![CDATA[Nested Set Model]]></category>

		<guid isPermaLink="false">http://www.pure-performance.com/?p=102</guid>
		<description><![CDATA[SQL databases are not designed for hierarchical data since the data is stored in flat relational tables with no built in parent-child relationship methods (Oracle does have the connect_by function to help).  XML databases on the other hand are built for hierarchical data.

So with SQL databases we have a problem that requires a solution.  Thanks to the SQL gurus out there we have three models to resolve this issue.  In this post I will point you to these resources.]]></description>
			<content:encoded><![CDATA[<div style="float:right;display:inline;margin:0px 0px 0px 0px;"><script type="text/javascript"><!--
google_ad_client = "pub-1316867219585554";
/* 234x60, ppi */
google_ad_slot = "4700353166";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><p>SQL databases are not designed for hierarchical data since the data is stored in flat relational tables with no built in parent-child relationship methods (Oracle does have the <a href="http://www.dba-oracle.com/t_connect_by.htm">connect_by</a> function to help).  XML databases on the other hand are built for hierarchical data.</p>
<p>So with SQL databases we have a problem that requires a solution.  Thanks to the SQL gurus out there we have three models to resolve this issue.  In this post I will point you to these resources.</p>
<p>What is hierarchical data?  The best example of a hierarchical model is a company organizational chart; other examples are product categories, forum categories and site maps.  With a hierarchical model you have a tree like structure that needs to be traversed to get to the node you&#8217;re looking for.</p>
<p><img class="aligncenter size-full wp-image-103" title="Hierarchical Data" src="http://www.pure-performance.com/wp-content/uploads/2009/03/image001.png" alt="Hierarchical Data" width="438" height="222" /></p>
<h2>The Adjacency list model</h2>
<p>This is the simplest method to implement, but it&#8217;s the slowest due to recursion.  So if you know the table will be large, use one of the other models. For a small table this would be the answer.</p>
<p>You simply add a parent column that links to the parent entry.  The root entry will be NULL because it does not link to any other node.</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top"><strong>Node</strong></td>
<td valign="top"><strong>Parent Node</strong></td>
</tr>
<tr>
<td valign="top">Home</td>
<td valign="top"></td>
</tr>
<tr>
<td valign="top">Products</td>
<td valign="top">Home</td>
</tr>
<tr>
<td valign="top">CD&#8217;s</td>
<td valign="top">Products</td>
</tr>
<tr>
<td valign="top">LP&#8217;s</td>
<td valign="top">Products</td>
</tr>
<tr>
<td valign="top">Artists</td>
<td valign="top">Home</td>
</tr>
<tr>
<td valign="top">Genre</td>
<td valign="top">Artists</td>
</tr>
<tr>
<td valign="top">R&amp;B</td>
<td valign="top">Genre</td>
</tr>
<tr>
<td valign="top">Rock</td>
<td valign="top">Genre</td>
</tr>
<tr>
<td valign="top">About US</td>
<td valign="top">Home</td>
</tr>
</tbody>
</table>
<table style="text-align: left; height: 164px;" border="0" cellpadding="0" width="326">
<tbody>
<tr>
<td width="24%"><strong>CAT_ID</strong></td>
<td width="29%"><strong>NAME</strong></td>
<td width="42%"><strong>CAT_PARENT</strong></td>
</tr>
<tr>
<td width="24%">1</td>
<td width="29%">Home</td>
<td width="42%"></td>
</tr>
<tr>
<td width="24%">2</td>
<td width="29%">product</td>
<td width="42%">2</td>
</tr>
<tr>
<td width="24%">3</td>
<td width="29%">CD&#8217;s</td>
<td width="42%">2</td>
</tr>
<tr>
<td width="24%">4</td>
<td width="29%">LP&#8217;s</td>
<td width="42%">2</td>
</tr>
<tr>
<td width="24%">5</td>
<td width="29%">Artists</td>
<td width="42%">1</td>
</tr>
<tr>
<td width="24%">6</td>
<td width="29%">Genre</td>
<td width="42%">5</td>
</tr>
<tr>
<td width="24%">7</td>
<td width="29%">R&amp;B</td>
<td width="42%">6</td>
</tr>
<tr>
<td width="24%">8</td>
<td width="29%">Rock</td>
<td width="42%">6</td>
</tr>
<tr>
<td width="24%">9</td>
<td width="29%">About Us</td>
<td width="42%">1</td>
</tr>
</tbody>
</table>
<h4>Traversing the table</h4>
<blockquote><p>SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4</p>
<p>FROM category t1</p>
<p>LEFT JOIN category  t2 ON t2.cat_parent = t1.cat_id</p>
<p>LEFT JOIN category  t3 ON t3.cat_parent = t2.cat_id</p>
<p>LEFT JOIN category  t4 ON t4.cat_parent = t3.cat_id</p>
<p>WHERE t1.name = &#8216;Home&#8217;;</p></blockquote>
<table style="height: 100px;" border="0" cellpadding="0" width="560">
<tbody>
<tr>
<td><strong>LEV1</strong></td>
<td><strong>LEV2</strong></td>
<td><strong>LEV3</strong></td>
<td><strong>LEV4</strong></td>
</tr>
<tr>
<td>Home</td>
<td>Artists</td>
<td>Genre</td>
<td>R&amp;B</td>
</tr>
<tr>
<td>Home</td>
<td>Artists</td>
<td>Genre</td>
<td>Rock</td>
</tr>
<tr>
<td>Home</td>
<td>About Us</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Home</td>
<td>product</td>
<td>LP&#8217;s</td>
<td></td>
</tr>
<tr>
<td>Home</td>
<td>product</td>
<td>CD&#8217;s</td>
<td></td>
</tr>
</tbody>
</table>
<h4>Resources</h4>
<p><a href="http://philip.greenspun.com/sql/trees.html">Trees in Oracle </a> (using connect by)</p>
<p><a href="http://en.wikipedia.org/wiki/Adjacency_list">Adjacency list defined</a></p>
<p><a href="http://www.sqlsummit.com/AdjacencyList.htm">Adjacency list model </a> (Joe Celko )</p>
<h2>Materialized Path model</h2>
<p>The idea with the Materialized path model is to link each node in the hierarchy with its position in the tree.  This is done with a concatenated list of all the nodes ancestors.  This list is usually stored in a delimited string.  Note the &#8220;Linage&#8221; field below.</p>
<table style="height: 164px;" border="0" cellpadding="0" width="522">
<tbody>
<tr>
<td width="16%"><strong>CAT_ID</strong></td>
<td width="20%"><strong>NAME</strong></td>
<td width="30%"><strong>CAT_PARENT</strong></td>
<td width="29%" valign="top"><strong>Lineage</strong></td>
</tr>
<tr>
<td width="16%">1</td>
<td width="20%">Home</td>
<td width="30%"></td>
<td width="29%" valign="top">.</td>
</tr>
<tr>
<td width="16%">2</td>
<td width="20%">product</td>
<td width="30%">1</td>
<td width="29%" valign="top">.1</td>
</tr>
<tr>
<td width="16%">3</td>
<td width="20%">CD&#8217;s</td>
<td width="30%">2</td>
<td width="29%" valign="top">.1.2</td>
</tr>
<tr>
<td width="16%">4</td>
<td width="20%">LP&#8217;s</td>
<td width="30%">2</td>
<td width="29%" valign="top">.1.2</td>
</tr>
<tr>
<td width="16%">5</td>
<td width="20%">Artists</td>
<td width="30%">1</td>
<td width="29%" valign="top">.1</td>
</tr>
<tr>
<td width="16%">6</td>
<td width="20%">Genre</td>
<td width="30%">5</td>
<td width="29%" valign="top">.1. 5</td>
</tr>
<tr>
<td width="16%">7</td>
<td width="20%">R&amp;B</td>
<td width="30%">6</td>
<td width="29%" valign="top">.1. 5.6</td>
</tr>
<tr>
<td width="16%">8</td>
<td width="20%">Rock</td>
<td width="30%">6</td>
<td width="29%" valign="top">.1. 5.6</td>
</tr>
<tr>
<td width="16%">9</td>
<td width="20%">About Us</td>
<td width="30%">1</td>
<td width="29%" valign="top">.1</td>
</tr>
</tbody>
</table>
<h4>Traversing the table</h4>
<blockquote><p>Select lpad(&#8216;-&#8217;,length(t1.lineage))||t1.name listing</p>
<p>From category t1, category t2</p>
<p>Where t1.lineage like t2.lineage ||&#8217;%&#8217;</p>
<p>And t2.name = &#8216;Home&#8217;;</p>
<p>Order by t1.lineage;</p></blockquote>
<table style="height: 164px;" border="0" cellpadding="0" width="267">
<tbody>
<tr>
<td><strong>Listing</strong></td>
</tr>
<tr>
<td style="text-align: left;">Home</td>
</tr>
<tr>
<td>-product</td>
</tr>
<tr>
<td>&#8211;CD&#8217;s</td>
</tr>
<tr>
<td>&#8211;LP&#8217;s</td>
</tr>
<tr>
<td>-Artists</td>
</tr>
<tr>
<td>&#8211;Genre</td>
</tr>
<tr>
<td>&#8212;R&amp;B</td>
</tr>
<tr>
<td>&#8212;Rock</td>
</tr>
<tr>
<td>-About Us</td>
</tr>
</tbody>
</table>
<h4>Resources</h4>
<p><a href="http://www.sqlteam.com/article/more-trees-hierarchies-in-sql">More Trees &amp; Hierarchies in SQL</a></p>
<p><a href="http://www.dbazine.com/oracle/or-articles/tropashko4">Trees in SQL</a></p>
<p><a href="http://joecelkothesqlapprentice.blogspot.com/2006/05/using-materialized-path-to-create.html">Using Materialized Path to create a paths table</a></p>
<h2>The Nested Set Model</h2>
<p>This is the best model for selecting information out of a relational database but slow in adding and deleting. So if you have a static structure this would be your choice.</p>
<p>This model has been championed by <a href="http://www.celko.com/">Joe Celko</a> and is detailed in his articles and book &#8220;<a href="http://www.amazon.com/gp/product/1558609202?ie=UTF8&amp;tag=pureperforma&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1558609202">Trees and Hierarchies in SQL for Smarties</a><img style="border:none !important; margin:0px !important;" src="http://www.assoc-amazon.com/e/ir?t=pureperforma&amp;l=as2&amp;o=1&amp;a=1558609202" border="0" alt="" width="1" height="1" /><br />
&#8220;.</p>
<div id="attachment_104" class="wp-caption aligncenter" style="width: 431px"><img class="size-full wp-image-104" title="Nested Set Model" src="http://www.pure-performance.com/wp-content/uploads/2009/03/image002.png" alt="Nested Set Model" width="421" height="320" /><p class="wp-caption-text">Nested Set Model</p></div>
<table border="0" cellpadding="0" width="71%">
<tbody>
<tr>
<td width="17%"><strong>CAT_ID</strong></td>
<td width="20%"><strong>NAME</strong></td>
<td width="30%"><strong>CAT_PARENT</strong></td>
<td width="14%" valign="top"><strong>Left</strong></td>
<td width="14%" valign="top"><strong>Right</strong></td>
</tr>
<tr>
<td width="17%">1</td>
<td width="20%">Home</td>
<td width="30%"></td>
<td width="14%" valign="top">1</td>
<td width="14%" valign="top">18</td>
</tr>
<tr>
<td width="17%">2</td>
<td width="20%">product</td>
<td width="30%">1</td>
<td width="14%" valign="top">2</td>
<td width="14%" valign="top">7</td>
</tr>
<tr>
<td width="17%">3</td>
<td width="20%">CD&#8217;s</td>
<td width="30%">2</td>
<td width="14%" valign="top">3</td>
<td width="14%" valign="top">4</td>
</tr>
<tr>
<td width="17%">4</td>
<td width="20%">LP&#8217;s</td>
<td width="30%">2</td>
<td width="14%" valign="top">5</td>
<td width="14%" valign="top">6</td>
</tr>
<tr>
<td width="17%">5</td>
<td width="20%">Artists</td>
<td width="30%">1</td>
<td width="14%" valign="top">8</td>
<td width="14%" valign="top">15</td>
</tr>
<tr>
<td width="17%">6</td>
<td width="20%">Genre</td>
<td width="30%">5</td>
<td width="14%" valign="top">9</td>
<td width="14%" valign="top">14</td>
</tr>
<tr>
<td width="17%">7</td>
<td width="20%">R&amp;B</td>
<td width="30%">6</td>
<td width="14%" valign="top">10</td>
<td width="14%" valign="top">11</td>
</tr>
<tr>
<td width="17%">8</td>
<td width="20%">Rock</td>
<td width="30%">6</td>
<td width="14%" valign="top">12</td>
<td width="14%" valign="top">13</td>
</tr>
<tr>
<td width="17%">9</td>
<td width="20%">About Us</td>
<td width="30%">1</td>
<td width="14%" valign="top">16</td>
<td width="14%" valign="top">17</td>
</tr>
</tbody>
</table>
<h4>Traversing the table</h4>
<p>(t2 is the parent)</p>
<blockquote><p>SELECT  lpad(&#8216;-&#8217;,COUNT(t2.name)-1)||t1.name,t1.left_node</p>
<p><span style="text-decoration: underline;">FROM</span> category t1,category t2</p>
<p>WHERE t1.left_node BETWEEN t2.left_node AND t2.right_node</p>
<p>GROUP BY t1.left_node,t1.name</p>
<p>order by t1.left_node;</p></blockquote>
<table style="height: 164px;" border="0" cellpadding="0" width="374">
<tbody>
<tr>
<td><strong>Listing</strong></td>
<td><strong>LEFT_NODE</strong></td>
</tr>
<tr>
<td>Home</td>
<td>1</td>
</tr>
<tr>
<td>-product</td>
<td>2</td>
</tr>
<tr>
<td>&#8211;CD&#8217;s</td>
<td>3</td>
</tr>
<tr>
<td>&#8211;LP&#8217;s</td>
<td>5</td>
</tr>
<tr>
<td>-Artists</td>
<td>8</td>
</tr>
<tr>
<td>&#8211;Genre</td>
<td>9</td>
</tr>
<tr>
<td>&#8212;R&amp;B</td>
<td>10</td>
</tr>
<tr>
<td>&#8212;Rock</td>
<td>12</td>
</tr>
<tr>
<td>-About Us</td>
<td>16</td>
</tr>
</tbody>
</table>
<h4>Resources</h4>
<p><a href="http://www.sitepoint.com/article/hierarchical-data-database/">Storing Hierarchical Data in a Database</a> (using PHP)</p>
<p><a href="http://dev.mysql.com/tech-resources/articles/hierarchical-data.html">Managing Hierarchical data in MySql</a></p>
<p><a href="http://www.dbmsmag.com/9604d06.html">Sql for Smarities article</a> (Joe Celko)</p>
<p><a href="http://en.wikipedia.org/wiki/Nested_set_model">Nested Set Model defined</a></p>
<h2>Definitions</h2>
<p><strong>Node</strong> &#8211; Abstract basic unit used to build linked data structures. Each node contains data and possibly links to other nodes.</p>
<p><strong>Root</strong> &#8211; Node with no parents.</p>
<p><strong>Leaf</strong> &#8211; Node with no children</p>
<p><strong>Child</strong> &#8211; direct subordinate node.</p>
<p><strong>Sibling</strong> &#8211; Node that shares the same parent.</p>
<p><strong>Ancestors</strong> &#8211; Parent or other superior node.</p>
<p><strong>Descendants</strong> &#8211; all subordinate nodes</p>
<div style="text-align:center;width:100%;"><div style="margin:0px 0px 0px 0px;"><script type="text/javascript"><!--
google_ad_client = "pub-1316867219585554";
/* 728x90, ppi */
google_ad_slot = "8229743782";
google_ad_width = 728;
google_ad_height = 90;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div></div>]]></content:encoded>
			<wfw:commentRss>http://www.pure-performance.com/2009/03/managing-hierarchical-data-in-sql/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
