<?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"
	>

<channel>
	<title>Alan deLevie</title>
	<atom:link href="http://www.alandelevie.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.alandelevie.com</link>
	<description>The website of Alan deLevie</description>
	<pubDate>Tue, 11 Nov 2008 19:41:55 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>bit.ly and teaching the machine</title>
		<link>http://www.alandelevie.com/2008/11/05/bitly-and-teaching-the-machine/</link>
		<comments>http://www.alandelevie.com/2008/11/05/bitly-and-teaching-the-machine/#comments</comments>
		<pubDate>Wed, 05 Nov 2008 02:35:53 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[bit.ly]]></category>

		<category><![CDATA[delicious]]></category>

		<category><![CDATA[digg]]></category>

		<category><![CDATA[open calais]]></category>

		<category><![CDATA[recaptcha]]></category>

		<category><![CDATA[semantic web]]></category>

		<category><![CDATA[twitturly]]></category>

		<guid isPermaLink="false">http://www.alandelevie.com/?p=155</guid>
		<description><![CDATA[It&#8217;s been a while since my last post. Since then I have been learning Python and Django. I definitely prefer Python to PHP. What I love about Python (and using Django) is that it allows a novice like myself to make relatively complex applications without frying my brain. One of my first projects with Django was [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a while since my last post. Since then I have been learning Python and <a href="http://www.djangoproject.com/" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.djangoproject.com');">Django</a>. I definitely prefer Python to PHP. What I love about Python (and using Django) is that it allows a novice like myself to make relatively complex applications without frying my brain. One of my first projects with Django was to make a url shortener.</p>
<p>After I made a simple prototype, I began thinking about what really happens when someone shortens a url. Sharing is the only reason to shorten. It is inherent in the nature of shortening. The sender is making the &#8220;package&#8221; of the content more palatable to the recipient(s).</p>
<p>Think of the sending of links from person to person as a flow of information. Knowing who is sending what to whom is powerful. This information reveals shared interests between different people&#8211;the heart of social bookmarking. It also shows relationships between people, places, things, and ideas&#8211;the heart of the <a href="http://www.youtube.com/watch?v=NLlGopyXT_g" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.youtube.com');">semantic web</a>. However, this flow is largely unharnessed. For example, sending links via instant messenger, e-mail, and Facebook go unnoticed by the &#8220;machine&#8221; we call the Internet. Twitter seems to be changing that. Twitter has become a hub for link-sharing.</p>
<p><span id="more-155"></span></p>
<p>One site, <a href="http://twitturly.com/" onclick="javascript:pageTracker._trackPageview('/outbound/article/twitturly.com');">Twitturly</a>, uses spiders to track all of the links shared on Twitter. It then ranks the most-shared links on a Digg-style home page. The theory and execution of the site are pretty slick.</p>
<p>However, more importantly, by limiting &#8221;tweets&#8221; to 140 characters, Twitter has created a huge market for link shortening.</p>
<p><a href="http://bit.ly/" onclick="javascript:pageTracker._trackPageview('/outbound/article/bit.ly');">Bit.ly</a> is a rising star among link shorteners. Registered users can keep track of their shortened links as well as how much traffic their shortened links have garnered. It caches each page it links to as well as processes each page using Reuters&#8217; Open Calais technology. Open Calais automatically extracts information about entities such as people and places from unstructured text.</p>
<p>On Oct. 31, Bit.ly <a href="http://blog.bit.ly/post/57297640/yesterdays-top-bits" onclick="javascript:pageTracker._trackPageview('/outbound/article/blog.bit.ly');">posted</a> the day&#8217;s most-visited shortened links.  The links aren&#8217;t too special (one is a streaming episode of the show Dexter), but the idea is powerful. Bit.ly is owned by <a href="http://betaworks.com/" onclick="javascript:pageTracker._trackPageview('/outbound/article/betaworks.com');">Betaworks</a>, whose <a href="http://search.twitter.com/" onclick="javascript:pageTracker._trackPageview('/outbound/article/search.twitter.com');">Summize</a> search engine was <a href="http://betaworks.com/post/42350393/summize-acquired-by-twitter" onclick="javascript:pageTracker._trackPageview('/outbound/article/betaworks.com');">acquired</a> by and integrated with Twitter. It is not unreasonable to think that Twitter will soon make Bit.ly its default url shortener. If Bit.ly can get a vast number of shortened links, it will be sitting on the type of data that can put it above the ranks of Delicious and Digg. Just think what one can do by combining raw traffic stats with the number of people shortening (think sharing) a given url.</p>
<p>The problem with Delicious and Digg is that users can only send links (in a meaningful way) to other registered users. It doesn&#8217;t tap into the flow of sent links. It creates its own, smaller flow instead. Delicious and Digg are unable to track url popularity beyond their own borders. Bit.ly on the other hand, taps into the already-existing flow of shared shortened links. It doesn&#8217;t matter how a Bit.ly url is sent. Bit.ly operates within an infinite universe, so to speak.</p>
<p>Bit.ly reminds me of another interesting web service, <a href="http://recaptcha.net/" onclick="javascript:pageTracker._trackPageview('/outbound/article/recaptcha.net');">RECAPTCHA</a>. In a nutshell, RECAPTCHA provides a utility to one group (spam prevention) while simultaneously providing utility to another group (using its data to refine text recognition software). Similarly, Bit.ly provides the utility of link shortening with the utility of social bookmarking with automatic semantic tagging.</p>
<p>Bit.ly has the potential to be one giant leap forward toward the advent of the much-hyped semantic web.</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fwww.alandelevie.com%2F2008%2F11%2F05%2Fbitly-and-teaching-the-machine%2F';
  addthis_title  = 'bit.ly+and+teaching+the+machine';
  addthis_pub    = '';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://www.alandelevie.com/2008/11/05/bitly-and-teaching-the-machine/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Build your own Penn State community site using Dapper</title>
		<link>http://www.alandelevie.com/2008/08/27/build-your-own-penn-state-community-site-using-dapper/</link>
		<comments>http://www.alandelevie.com/2008/08/27/build-your-own-penn-state-community-site-using-dapper/#comments</comments>
		<pubDate>Wed, 27 Aug 2008 04:26:00 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[penn state]]></category>

		<category><![CDATA[dapper]]></category>

		<guid isPermaLink="false">http://www.alandelevie.com/?p=101</guid>
		<description><![CDATA[
It has been an observation of mine that some of the best online communities are the ones that most effectively mimic offline communities. Take Facebook for example. In my opinion, Facebook owes much of its success to its members&#8217; use of real names. My news feed doesn&#8217;t say &#8220;OgReSLAYER91 is friends with Xx1337haXzorxX.&#8221; Instead, it [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.alandelevie.com/images/phdapperschematic.gif" alt="" /></p>
<p>It has been an observation of mine that some of the best online communities are the ones that most effectively mimic offline communities. Take Facebook for example. In my opinion, Facebook owes much of its success to its members&#8217; use of real names. My news feed doesn&#8217;t say &#8220;OgReSLAYER91 is friends with Xx1337haXzorxX.&#8221; Instead, it could say &#8220;Steve Ballmer is friends with Bill Gates.&#8221; This adds tremendous value to a social network. To tap into this value, many developers turn to the Facebook API. Sometimes it makes no sense to start a social network from scratch. However, for Penn State-oriented developers, there is a decent alternative.</p>
<p><span id="more-101"></span></p>
<p>Penn State has an online directory, <a href="http://www.psu.edu/ph" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.psu.edu');">psu.edu/ph</a>, where anyone can enter information about a student or faculty member at Penn State and find out information such as their full name, major, address, and a few other bits of miscellany. Using Dapper, I made a script which outputs a Penn State student&#8217;s or faculty member&#8217;s full name given their user id.</p>
<p>So a Penn State-oriented community site or social network would accept only those with a &#8220;userid&#8221;@psu.edu email address. Here&#8217;s a little proof of concept script to get started:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> ?php
<span style="color: #000033;">$userid</span> <span style="color: #339933;">=</span> <span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;@&quot;</span><span style="color: #339933;">,</span> <span style="color: #000033;">$_GET</span><span style="color: #009900;">&#91;</span>userid<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//user inputs email address</span>
<span style="color: #000033;">$domains</span> <span style="color: #339933;">=</span> <span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;.&quot;</span><span style="color: #339933;">,</span> <span style="color: #000033;">$userid</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000033;">$domains</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">!==</span> <span style="color: #0000ff;">&quot;psu&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> <span style="color: #666666; font-style: italic;">//checks for psu domain</span>
<span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;
&nbsp;
Sorry, we are only accepting registration from Penn State students.&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span>
<span style="color: #000033;">$xml</span> <span style="color: #339933;">=</span> simplexml_load_file<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;http://www.dapper.net/RunDapp?dappName=psuph&amp;amp;v=1&amp;amp;v_userid=&quot;</span><span style="color: #339933;">.</span><span style="color: #000033;">$userid</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//runs my dapp</span>
<span style="color: #000033;">$name</span> <span style="color: #339933;">=</span> <span style="color: #000033;">$xml</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>name<span style="color: #339933;">;</span>
<span style="color: #000033;">$pieces</span> <span style="color: #339933;">=</span> <span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot; &quot;</span><span style="color: #339933;">,</span> <span style="color: #000033;">$name</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">function</span> uppercase<span style="color: #009900;">&#40;</span><span style="color: #000033;">$string</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
<span style="color: #000033;">$string</span> <span style="color: #339933;">=</span> <span style="color: #990000;">ucfirst</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">strtolower</span><span style="color: #009900;">&#40;</span><span style="color: #000033;">$string</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//converts all uppercase names to only first letter uppercased</span>
<span style="color: #990000;">echo</span> <span style="color: #000033;">$string</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;
&nbsp;
Welcome, &quot;</span><span style="color: #339933;">;</span>
uppercase<span style="color: #009900;">&#40;</span><span style="color: #000033;">$pieces</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//outputs first name</span>
<span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot; &quot;</span><span style="color: #339933;">;</span>
uppercase<span style="color: #009900;">&#40;</span><span style="color: #000033;">$pieces</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//outputs middle name</span>
<span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot; &quot;</span><span style="color: #339933;">;</span>
uppercase<span style="color: #009900;">&#40;</span><span style="color: #000033;">$pieces</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//outputs last name</span>
<span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;!
&nbsp;
&lt;em&gt;a confirmation code has been sent to &quot;</span><span style="color: #339933;">.</span><span style="color: #000033;">$_GET</span><span style="color: #009900;">&#91;</span>userid<span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;&lt;/em&gt;
&nbsp;
&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
?<span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span></pre></div></div>

<p>The script accepts an email address then checks if it&#8217;s from Penn State. If it is from Penn State, the script (via Dapper) scrapes the person&#8217;s name from Penn State&#8217;s ph server, parses some xml and then outputs a nicely formatted name.</p>
<p>I&#8217;ve been playing around with this Dapp, trying to have it collect other data, such as addresses, but it is much less accurate.</p>
<p>I&#8217;d like to get a flash widget of this Dapp up, but have thus far experienced some difficulty. Until then, you can run the actual script <a href="http://www.alandelevie.com/scripts/phdapp.php?userid=add5087@psu.edu" >here</a>. Feel free to change the userid in the address bar of your browser to test it out yourself.</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fwww.alandelevie.com%2F2008%2F08%2F27%2Fbuild-your-own-penn-state-community-site-using-dapper%2F';
  addthis_title  = 'Build+your+own+Penn+State+community+site+using+Dapper';
  addthis_pub    = '';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://www.alandelevie.com/2008/08/27/build-your-own-penn-state-community-site-using-dapper/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Penn State&#8217;s Schedule of Courses &#8212; un-&#8221;dapped&#8221; potential</title>
		<link>http://www.alandelevie.com/2008/07/18/penn-states-schedule-of-courses-un-dapped-potential/</link>
		<comments>http://www.alandelevie.com/2008/07/18/penn-states-schedule-of-courses-un-dapped-potential/#comments</comments>
		<pubDate>Fri, 18 Jul 2008 03:18:20 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[penn state]]></category>

		<category><![CDATA[dapper]]></category>

		<guid isPermaLink="false">http://www.alandelevie.com/?p=77</guid>
		<description><![CDATA[Daehee Park recently wrote about scaping Penn State&#8217;s Schedule of Courses to create a free API of course data. His method of choice was to use Beautiful Soup for Python. As I have yet to learn Python, I will be taking a different approach towards the same end: Dapper. Dapper bills itself as a tool [...]]]></description>
			<content:encoded><![CDATA[<p>Daehee Park recently wrote about <a href="http://www.itmilk.com/2008/07/15/scraping-penn-states-schedule-of-courses/" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.itmilk.com');">scaping Penn State&#8217;s Schedule of Courses</a> to create a free API of course data. His method of choice was to use Beautiful Soup for Python. As I have yet to learn Python, I will be taking a different approach towards the same end: <a href="http://www.dapper.net" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.dapper.net');">Dapper</a>. Dapper bills itself as a tool for creating <a href="http://www.techcrunch.com/2006/08/17/create-an-api-for-any-site-with-dapper/" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.techcrunch.com');">an API for any website</a>&#8211;hopefully this includes schedule.psu.edu.</p>
<p><span id="more-77"></span></p>
<p>To use Dapper, you must &#8220;train&#8221; it how to scrape your desired data. It supposedly works best on templated pages. You simply supply the &#8220;Dapp factory&#8221; tool with several urls of pages that use the same template. Then you highlight the desired data to scrape from each url. This process is very hit-or-miss. Selecting one piece of data may cause other data to be sporadically selected. Sometimes this data is what you wanted (in which case you may find yourself praising its algorithm as genius) and sometimes the data isn&#8217;t quite what you had in mind (in which case you&#8217;ll be cursing the algorithm for wasting so much of your time). Ilan Flint, of Dapper Support <a href="http://forum.dapper.net/viewtopic.php?f=4&amp;t=17#p41" onclick="javascript:pageTracker._trackPageview('/outbound/article/forum.dapper.net');">wrote</a>:</p>
<blockquote><p>Dapper&#8217;s method of action is finding an algorithm that will &#8220;understand&#8221; , in machine terms, what is the content that you wanted to choose.</p>
<p>The purpose and meaning of each element in a web page, something that is very intuitively understood by you, is completely incoherent to a computer, and that&#8217;s the gap that Dapper bridges.</p></blockquote>
<p>Once your &#8220;dapp&#8221; has been created, you can choose from a wide variety of output formats including xml, rss, iCal, Google Maps, and html to name a few. There is even a feature where you can &#8220;link&#8221; the output of one dapp to be the input of another dapp.</p>
<p>While Dapper has huge potential, it can be very unrefined at times. It has been slow/crashing more than half the time I&#8217;ve been using it. I found that it works best using the Opera browser instead of the more mainstream Firefox and Safari. The folks over at Dapper are aware of these issues and are working on them. This is what Flint wrote to me in a support email reply to a question about the site&#8217;s performance issues:</p>
<blockquote><p>What you experienced was a temporary issue - one that hopefully<br />
will not repeat itself.</p>
<p>Dapper is aware of these issues popping-up every now and then,<br />
and is constantly working hard to improve the stability and reliability.</p></blockquote>
<p>You&#8217;ve still gotta give the Dapper people credit. Their interface uses ajax&#8211;something which can be prone to crashing and is still full of compatibility issues. I think they will continue to face an uphill battle when it comes to ensuring a smooth user experience.</p>
<p>Nevertheless, I can see many neat possibilities using the Penn State Schedule of Courses and Dapper. Here are some that sprang to mind:</p>
<ul>
<li>an rss feed for the number of seat openings left in a given course</li>
<li>a Google Maps mashup of a student&#8217;s course schedule, showing schedule possibilities that require the least amount of walking (or the most amount of walking if you&#8217;d like to stave off those freshmen 15)</li>
<li>an iCal or Google Calendar mashup in which a student&#8217;s schedule can be easily imported into one of those formats</li>
</ul>
<p>I&#8217;ll be trying to bring these ideas to fruition, but feel free to beat me to it.</p>
<p>In the meantime, you can play with a flash widget of a dapp I made. Simply type in a semester, campus, and department and the widget will return a list of course numbers. Don&#8217;t know where to begin? Try typing &#8220;fall&#8221; for semester, &#8220;up&#8221; for campus, and &#8220;pl_sc&#8221; for department. There may be some errors and I make no claims about the accuracy of the widget.</p>
<table border="0" width="251">
<tbody>
<tr>
<td><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="251" height="304" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="flashvars" value="dappURL=http://www.dapper.net/RunDapp?dappName=get_courses_and_sectionVersion4theonethatshouldwork&amp;v=1&amp;showTitles=undefined&amp;showGroups=false&amp;fieldsNames=course number^course number&amp;argsFixed=&amp;argsInputs=semester^^variableArg_0|campus^^variableArg_1|department^^variableArg_2&amp;menuMode=2&amp;boxTitle=Penn State courses&amp;bkgColor=13880755&amp;isLogin=false&amp;contentSiteURL=schedule.psu.edu" /><param name="src" value="http://www.dapper.net/widget/tnwidget.swf" /><param name="wmode" value="transparent" /><embed type="application/x-shockwave-flash" width="251" height="304" src="http://www.dapper.net/widget/tnwidget.swf" wmode="transparent" flashvars="dappURL=http://www.dapper.net/RunDapp?dappName=get_courses_and_sectionVersion4theonethatshouldwork&amp;v=1&amp;showTitles=undefined&amp;showGroups=false&amp;fieldsNames=course number^course number&amp;argsFixed=&amp;argsInputs=semester^^variableArg_0|campus^^variableArg_1|department^^variableArg_2&amp;menuMode=2&amp;boxTitle=Penn State courses&amp;bkgColor=13880755&amp;isLogin=false&amp;contentSiteURL=schedule.psu.edu"></embed></object></td>
</tr>
<tr>
<td>
<table style="height: 13px;" border="0" width="251">
<tbody>
<tr>
<td align="left"><a style="text-decoration: none;" href="http://www.dapper.net/widget/embed.php?dappName=get_courses_and_sectionVersion4theonethatshouldwork&amp;embedParams=dappURL%3Dhttp%3A%2F%2Fwww%2Edapper%2Enet%2FRunDapp%3FdappName%3Dget%5Fcourses%5Fand%5FsectionVersion4theonethatshouldwork%26v%3D1%26showTitles%3Dundefined%26showGroups%3Dfalse%26fieldsNames%3Dcourse%20number%5Ecourse%20number%26argsFixed%3D%26argsInputs%3Dsemester%5E%5EvariableArg%5F0%7Ccampus%5E%5EvariableArg%5F1%7Cdepartment%5E%5EvariableArg%5F2%26menuMode%3D2%26boxTitle%3DPenn%20State%20courses%26bkgColor%3D13880755%26isLogin%3Dfalse%26contentSiteURL%3Dschedule%2Epsu%2Eedu" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.dapper.net');" target="_blank"><img src="http://www.dapper.net/images/widget-add.gif" border="0" alt="" width="13" height="13" /><span style="font-size: 9px; font-family: verdana; color: #0066ff;"> Add to your site</span></a></td>
<td></td>
<td align="right"><a style="text-decoration: none;" href="http://www.dapper.net" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.dapper.net');" target="_blank"><span style="font-size: 9px; font-family: verdana; color: #cccccc;">powered by</span><span style="font-size: 9px; font-family: verdana; color: #0066ff;"> Dapper </span><img src="http://www.dapper.net/images/widget-logo.gif" border="0" alt="" width="13" height="13" /></a></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fwww.alandelevie.com%2F2008%2F07%2F18%2Fpenn-states-schedule-of-courses-un-dapped-potential%2F';
  addthis_title  = 'Penn+State%26%238217%3Bs+Schedule+of+Courses+%26%238212%3B+un-%26%238221%3Bdapped%26%238221%3B+potential';
  addthis_pub    = '';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://www.alandelevie.com/2008/07/18/penn-states-schedule-of-courses-un-dapped-potential/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Recursion-less storage of hierarchical data in a relational database</title>
		<link>http://www.alandelevie.com/2008/07/12/recursion-less-storage-of-hierarchical-data-in-a-relational-database/</link>
		<comments>http://www.alandelevie.com/2008/07/12/recursion-less-storage-of-hierarchical-data-in-a-relational-database/#comments</comments>
		<pubDate>Sat, 12 Jul 2008 19:07:02 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[sql]]></category>

		<category><![CDATA[hierarchical data]]></category>

		<category><![CDATA[modified preorder tree traversal algorithm]]></category>

		<category><![CDATA[path enumeration]]></category>

		<category><![CDATA[recursion]]></category>

		<guid isPermaLink="false">http://www.alandelevie.com/?p=11</guid>
		<description><![CDATA[One of the main problems with using a relational database such as MySQL is that it can be tricky to store and retrieve hierarchical information. Hierarchies are expressed with tree structures whereas relational databases use flat tables. So how can one fit this square peg into a round hole? Fortunately, there are several methods out [...]]]></description>
			<content:encoded><![CDATA[<p>One of the main problems with using a relational database such as MySQL is that it can be tricky to store and retrieve hierarchical information. Hierarchies are expressed with tree structures whereas relational databases use flat tables. So how can one fit this square peg into a round hole? Fortunately, there are several methods out there. Unfortunately most of these methods rely on recursion for either populating, updating, or deleting parts of tree. Check out this <a href="http://www.evolt.org/article/Four_ways_to_work_with_hierarchical_data/17/4047/index.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.evolt.org');">evolt</a> article to learn more about the pitfalls of recursion (and even more ways to store hierarchical data). Here&#8217;s a quick overview of two methods which require recursion and one which never requires it.</p>
<p><span id="more-11"></span></p>
<p><span style="text-decoration: underline;">Method 1: Parent/child</span></p>
<p>This is the most straightforward method.<br />
</p>
<table class="wptable rowstyle-alt" id="wptable-2"  cellspacing="1" cellpadding="1">
	<thead>
	<tr>
		<th class="sortable" style="width:30px" align="center">id</th>
		<th class="sortable" style="width:30px" align="center">element</th>
		<th class="sortable" style="width:30px" align="center">parent</th>
	</tr>
	</thead>
	<tr>
		<td style="width:30px" align="center">1</td>
		<td style="width:30px" align="center">fruit</td>
		<td style="width:30px" align="center">null</td>
	</tr>
	<tr class="alt">
		<td style="width:30px" align="center">2</td>
		<td style="width:30px" align="center">orange</td>
		<td style="width:30px" align="center">1</td>
	</tr>
	<tr>
		<td style="width:30px" align="center">3</td>
		<td style="width:30px" align="center">apple</td>
		<td style="width:30px" align="center">1</td>
	</tr>
	<tr class="alt">
		<td style="width:30px" align="center">4</td>
		<td style="width:30px" align="center">granny-smith</td>
		<td style="width:30px" align="center">3</td>
	</tr>
	<tr>
		<td style="width:30px" align="center">5</td>
		<td style="width:30px" align="center">red delicious</td>
		<td style="width:30px" align="center">3</td>
	</tr>
</table><p>
<br />
Each row contains the name of the element, its unique id and the unique id of its parent element. Every child has one and only one parent but a parent may have any number of children.<br />
<img class="alignnone" src="http://www.alandelevie.com/images/applehierarchy.gif" alt="a hierarchy of fruit" /><br />
A php function for converting such a table into a hierarchical tree could look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> ?php
<span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">&quot;dbconnect.php&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> show_hierarchy_1<span style="color: #009900;">&#40;</span><span style="color: #000033;">$rootid</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #000033;">$query</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT * FROM table WHERE parent  '$rootid'&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000033;">$result</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #000033;">$query</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #000033;">$row</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_fetch_array</span><span style="color: #009900;">&#40;</span><span style="color: #000033;">$result</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
&nbsp;
     <span style="color: #990000;">echo</span> <span style="color: #000033;">$row</span><span style="color: #009900;">&#91;</span>element<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
     <span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">;</span>
&nbsp;
     show_hierarchy_1<span style="color: #009900;">&#40;</span><span style="color: #000033;">$row</span><span style="color: #009900;">&#91;</span>id<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
 <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
?<span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span></pre></div></div>

<p>Notice that this function is recursive. While dead-simple to understand, this function will use more and more processing resources as the database grows in size. There must be a better way. Enter method two.</p>
<p><span style="text-decoration: underline;">Method 2: the modified preorder tree traversal algorithm</span></p>
<p>When I first read <a href="http://www.sitepoint.com/print/hierarchical-data-database" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.sitepoint.com');">Sitepoint&#8217;s</a> article about this, I was excited to find a method that did not require recursion to retrieve the hierarchy. Have a look-see:<br />
</p>
<table class="wptable rowstyle-alt" id="wptable-3"  cellspacing="1" cellpadding="1">
	<thead>
	<tr>
		<th class="sortable" style="width:30px" align="center">element</th>
		<th class="sortable" style="width:30px" align="center">lt</th>
		<th class="sortable" style="width:30px" align="center">rt</th>
	</tr>
	</thead>
	<tr>
		<td style="width:30px" align="center">fruit</td>
		<td style="width:30px" align="center">1</td>
		<td style="width:30px" align="center">10</td>
	</tr>
	<tr class="alt">
		<td style="width:30px" align="center">orange</td>
		<td style="width:30px" align="center">2</td>
		<td style="width:30px" align="center">3</td>
	</tr>
	<tr>
		<td style="width:30px" align="center">apple</td>
		<td style="width:30px" align="center">4</td>
		<td style="width:30px" align="center">9</td>
	</tr>
	<tr class="alt">
		<td style="width:30px" align="center">granny-smith</td>
		<td style="width:30px" align="center">5</td>
		<td style="width:30px" align="center">6</td>
	</tr>
	<tr>
		<td style="width:30px" align="center">red-delicious</td>
		<td style="width:30px" align="center">7</td>
		<td style="width:30px" align="center">8</td>
	</tr>
</table><p>
<br />
Each element has a left value and a right value. The values are determined by traversing the tree starting from the left of the root element. This diagram can explain the process far easier than words can:<br />
<img class="alignnone" src="http://www.alandelevie.com/images/applehierarchy-mptta.gif" alt="using the modified preorder tree traversal algorithm" /></p>
<p>Now this is where the magic happens. A php function to retrieve the whole tree would look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> ?php
<span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">&quot;dbconnect.php&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> show_hierarchy_2<span style="color: #009900;">&#40;</span><span style="color: #000033;">$rootid</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #000033;">$query</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT * FROM table WHERE id = '$rootid'&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000033;">$result</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #000033;">$query</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #000033;">$row</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_fetch_array</span><span style="color: #009900;">&#40;</span><span style="color: #000033;">$result</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
&nbsp;
     <span style="color: #000033;">$query2</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT * FROM table WHERE lt &amp;gt; $row[lt] AND rt &amp;lt; $row[rt]&quot;</span><span style="color: #339933;">;</span>
     <span style="color: #000033;">$result2</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #000033;">$query2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
     <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #000033;">$row2</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_fetch_array</span><span style="color: #009900;">&#40;</span><span style="color: #000033;">$result2</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
&nbsp;
         <span style="color: #990000;">echo</span> <span style="color: #000033;">$row2</span><span style="color: #009900;">&#91;</span>element<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
         <span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">;</span> 
&nbsp;
  <span style="color: #009900;">&#125;</span>
 <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
?<span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span></pre></div></div>

<p>The simplicity of retrieving a hierarchy given a parent element&#8217;s left and right values is astounding. With a single query of the database, an entire tree is displayed, no recursion necessary. Unfortunately the modified preorder tree traversal algorithm has some potentially deal-breaking downsides. The first downside is the issue of populating a table with left and right values. Gijs Van Tulder (author of the Sitepoint article) provides such a method, given a table that already has parent/child values for each row.<br />
The following is Tulder&#8217;s work:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> ?php
<span style="color: #000000; font-weight: bold;">function</span> rebuild_tree<span style="color: #009900;">&#40;</span><span style="color: #000033;">$parent</span><span style="color: #339933;">,</span> <span style="color: #000033;">$left</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
   <span style="color: #666666; font-style: italic;">// the right value of this node is the left value + 1</span>
   <span style="color: #000033;">$right</span> <span style="color: #339933;">=</span> <span style="color: #000033;">$left</span><span style="color: #cc66cc;">+1</span><span style="color: #339933;">;</span>
&nbsp;
   <span style="color: #666666; font-style: italic;">// get all children of this node</span>
   <span style="color: #000033;">$result</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'SELECT title FROM tree '</span><span style="color: #339933;">.</span>
                          <span style="color: #0000ff;">'WHERE parent=&quot;'</span><span style="color: #339933;">.</span><span style="color: #000033;">$parent</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #000033;">$row</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_fetch_array</span><span style="color: #009900;">&#40;</span><span style="color: #000033;">$result</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
       <span style="color: #666666; font-style: italic;">// recursive execution of this function for each</span>
       <span style="color: #666666; font-style: italic;">// child of this node</span>
       <span style="color: #666666; font-style: italic;">// $right is the current right value, which is</span>
       <span style="color: #666666; font-style: italic;">// incremented by the rebuild_tree function</span>
       <span style="color: #000033;">$right</span> <span style="color: #339933;">=</span> rebuild_tree<span style="color: #009900;">&#40;</span><span style="color: #000033;">$row</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'title'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #000033;">$right</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #009900;">&#125;</span>
&nbsp;
   <span style="color: #666666; font-style: italic;">// we've got the left value, and now that we've processed</span>
   <span style="color: #666666; font-style: italic;">// the children of this node we also know the right value</span>
   <span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'UPDATE tree SET lft='</span><span style="color: #339933;">.</span><span style="color: #000033;">$left</span><span style="color: #339933;">.</span><span style="color: #0000ff;">', rgt='</span><span style="color: #339933;">.</span>
                <span style="color: #000033;">$right</span><span style="color: #339933;">.</span><span style="color: #0000ff;">' WHERE title=&quot;'</span><span style="color: #339933;">.</span><span style="color: #000033;">$parent</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
   <span style="color: #666666; font-style: italic;">// return the right value of this node + 1</span>
   <span style="color: #b1b100;">return</span> <span style="color: #000033;">$right</span><span style="color: #cc66cc;">+1</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
?<span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span></pre></div></div>

<p>Tulder writes:</p>
<blockquote><p>The recursion makes this a fairly complex function to understand. However, this function achieves the same result we did by hand at the beginning of this section. It walks around the tree, adding one for each node it sees. After you&#8217;ve run this function, you&#8217;ll see that the left and right values are still the same (a quick check: the right value of the root node should be twice the number of nodes).</p></blockquote>
<p>Remember, we want to <em>avoid</em> recursion. Recursion is slow. Furthermore, modifying the tree requires recursion. Tulder explains two methods:</p>
<blockquote><p>The first option is simple. You use the adjacency list method for updating, and the modified preorder tree traversal algorithm for retrieval. If you want to add a new node, you just add it to the table and set the parent column. Then, you simply rerun the rebuild_tree() function. This is easy, but not very efficient with large trees.</p>
<p>The second way to add, and delete nodes is to update the left and right values of all nodes to the right of the new node.</p></blockquote>
<p>Tulder&#8217;s second method may be very light on system resources in one circumstance, and very heavy in another. For example, adding an element whose parent is the root element will not spare much processing power.</p>
<p>And this brings us to the wonderful third way.</p>
<p><span style="text-decoration: underline;">Method 3: David Chandler&#8217;s patent</span></p>
<p>David Chandler, apparently is a programmer. <a href="http://www.google.com/search?hl=en&amp;safe=off&amp;q=%22david+chandler%22+hierarchical+data&amp;btnG=Search" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.google.com');">Google</a> him around if you want. The important thing is that he devised a method of storing hierarchical data in a relational database where recursion is never needed.</p>
<p>You can read the <a href="http://www.patentstorm.us/patents/006480857.pdf" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.patentstorm.us');">patent</a> here. (Requires free registration)</p>
<p>Here&#8217;s the table:<br />
</p>
<table class="wptable rowstyle-alt" id="wptable-4"  cellspacing="1" cellpadding="1">
	<thead>
	<tr>
		<th class="sortable" style="width:30px" align="center">element</th>
		<th class="sortable" style="width:30px" align="center">L1</th>
		<th class="sortable" style="width:30px" align="center">L2</th>
		<th class="sortable" style="width:30px" align="center">L3</th>
	</tr>
	</thead>
	<tr>
		<td style="width:30px" align="center">fruit</td>
		<td style="width:30px" align="center">1</td>
		<td style="width:30px" align="center">0</td>
		<td style="width:30px" align="center">0</td>
	</tr>
	<tr class="alt">
		<td style="width:30px" align="center">orange</td>
		<td style="width:30px" align="center">1</td>
		<td style="width:30px" align="center">1</td>
		<td style="width:30px" align="center">0</td>
	</tr>
	<tr>
		<td style="width:30px" align="center">apple</td>
		<td style="width:30px" align="center">1</td>
		<td style="width:30px" align="center">2</td>
		<td style="width:30px" align="center">0</td>
	</tr>
	<tr class="alt">
		<td style="width:30px" align="center">granny-smith</td>
		<td style="width:30px" align="center">1</td>
		<td style="width:30px" align="center">2</td>
		<td style="width:30px" align="center">1</td>
	</tr>
	<tr>
		<td style="width:30px" align="center">red-delicious</td>
		<td style="width:30px" align="center">1</td>
		<td style="width:30px" align="center">2</td>
		<td style="width:30px" align="center">2</td>
	</tr>
</table><p>
</p>
<p>With this method, there will be a database column for each level of depth. The root element will only have the L1 column set. Its children will have the L1 and L2 columns set and their children will have the L1, L2 and L3 columns set and so on and so forth. If you have no idea how &#8220;deep&#8221; your hierarchy might be, this method may not be for you. Otherwise, keep reading.<br />
<img class="alignnone" src="http://www.alandelevie.com/images/applehierarchy-chandlers-1.gif" alt="using chandler\" /><br />
And here&#8217;s a php script to display the whole tree:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> ?php
<span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">&quot;dbconnect.php&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> show_hierarchy_3<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
<span style="color: #000033;">$query</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT * FROM table WHERE l1 != '0' ORDER BY l1, l2, l3, l4&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000033;">$result</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #000033;">$query</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #000033;">$row</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_fetch_array</span><span style="color: #009900;">&#40;</span><span style="color: #000033;">$result</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #000033;">$level</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000033;">$row</span><span style="color: #009900;">&#91;</span>l1<span style="color: #009900;">&#93;</span> <span style="color: #339933;">!=</span> <span style="color: #0000ff;">'0'</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000033;">$level</span> <span style="color: #339933;">=</span> <span style="color: #000033;">$level</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000033;">$row</span><span style="color: #009900;">&#91;</span>l2<span style="color: #009900;">&#93;</span> <span style="color: #339933;">!=</span> <span style="color: #0000ff;">'0'</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000033;">$level</span> <span style="color: #339933;">=</span> <span style="color: #000033;">$level</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000033;">$row</span><span style="color: #009900;">&#91;</span>l3<span style="color: #009900;">&#93;</span> <span style="color: #339933;">!=</span> <span style="color: #0000ff;">'0'</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000033;">$level</span> <span style="color: #339933;">=</span> <span style="color: #000033;">$level</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #990000;">echo</span> <span style="color: #990000;">str_repeat</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'___'</span><span style="color: #339933;">,</span><span style="color: #000033;">$level</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #990000;">echo</span> <span style="color: #000033;">$row</span><span style="color: #009900;">&#91;</span>element<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
	<span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
?<span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span></pre></div></div>

<p>Let&#8217;s say I want to add a child to the &#8220;orange&#8221; node:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> ?php
<span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">&quot;dbconnect.php&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;INSERT INTO `table` (
		`element` ,
		`l1` ,
  		`l2` ,
  		`l3`
		)
		VALUES (
		'valencia', '1', '1', '1'
		);&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
?<span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span></pre></div></div>

<p><img class="alignnone" src="http://www.alandelevie.com/images/applehierarchy-chandlers-2.gif" alt="using chandler\" /><br />
And that&#8217;s it. The tree was updated without recursion. Deleting nodes is very similar to adding, just use <code>DELETE FROM</code>. There&#8217;s no <code>update_tree()</code> function to run, you can just run the <code>show_hierarchy_3()</code> script.</p>
<p>Chandler&#8217;s method could be considered an adaptation of the <a href="http://www.onlamp.com/pub/a/onlamp/2004/08/05/hierarchical_sql.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.onlamp.com');">path enumeration model</a>. The main difference between the two is that the path enumeration model uses a single database column with a delimiter to show an element&#8217;s hierarchy, whereas Chandler&#8217;s method uses multiple columns. In the patent, Candler writes:</p>
<blockquote><p>Storing the digits of the Outline Number in separate columns allows for constructing very efficient queries of a type not possible with the prior art methods. In particular reference to the method shown in FIG. 3 , consider the steps required to move a data element within a tree (i.e. changing the Outline Number). First the Outline Number string needs to be parsed into the respective digits, then adding and subtracting the appropriate digits as necessary would need to be performed, and then the digits need to be converted back to string values and the new Outline Number reconstructed. By storing the digits of the Outline Number in separate columns the present invention substantially simplifies these operations by avoiding performing string operations that are typically slow and cumbersome to write, and by quickly isolating and operating on the appropriate digit in the Outline Number.</p></blockquote>
<p>So there you have it. Enjoy.</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fwww.alandelevie.com%2F2008%2F07%2F12%2Frecursion-less-storage-of-hierarchical-data-in-a-relational-database%2F';
  addthis_title  = 'Recursion-less+storage+of+hierarchical+data+in+a+relational+database';
  addthis_pub    = '';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://www.alandelevie.com/2008/07/12/recursion-less-storage-of-hierarchical-data-in-a-relational-database/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
