Sort Interface - tree structure
15 December 2006

Sorting a Modified Preorder Tree Traversal MySQL

I have always used adjacency list model to store hierarchical data in databases, and really had no problem with it. EXCEPT you had to use some kind of server side code to do any real managing of the structure. BUT, it was pretty easy to visualize and understand, then i read up on Nested Model/Preorder Tree Traversal and the modified version … a whole new world has opened up…

When i was tasked with creating a website/cms i wanted to present the admin a tree structure where they can see entire structure and edit/add/reorder whatever pages they wanted to (a screen shot at permanent link).

I read a few articles on storing hierarchical data in databases:
Managing Hierarchical Data in MySQL
Storing Hierarchical Data in a Database
Four ways to work with hierarchical data

and read a chapter or two from Joe Celko’s Trees and Hierarchies in SQL for Smarties

I chose modified preorder tree traversal which is basically the nested set model with a parent, so it’s kind of a hybrid between nested and adjacency model…

I am not going to spend my time going into any details about this structure, i am just not smart enough to do it, nor can i say i am 100% comfortable, so read the articles … it’s really a thing of beauty when you fully understand it …

So now i use mostly SQL, to retrieve data instead of any server side code… i kinda cheated, and run rebuild script when user deletes or adds a new node… it really works out well for me, but i must say it might be the lazy way out…

When user adds a new node, i make sure the parent is correct and set lft/rgt to some really high value that should never clash… then i run rebuild (again i said i am “lazy”) ... and that worked out really well…

Because I set lft/rgt to a high value, anything that gets added us always last, which is less than ideal… so what to do

I wrote article way back when … and why re-invent the wheel:
Maintain a sortorder column with a HTML/Javascript GUI … so how to re-use with minimal effort?

I found that I did not need to change the gui, except to store the parent id. ... my first run was to swap around the lfts + rgts , and then do children if it had children… but that seemed to be difficult to do … then it dawned on me … just give new lfts then run rebuild … and i went to code below …

SO first i grab the lft+rgt of parent id.. I then loop over the array and update lft + right based on order passed in … then i run rebuild

.
//GRAB PARENT LFT + RGT
//NOTE: I HAVE SQL WRAPPER THAT DOES THIS
//"SELECT  lft,rgt from MY_PAGE_TABLE 
//WHERE PARENT_ID=$pid"
​
$p_lft = LFT OF PARENT
$offset = 1; /
sql_query("LOCK TABLES MY_PAGE_TABLE WRITE");
foreach ($page_order_array as $page_id)
{
	//ADD SLASHES AROUND PARENT ID
	$page = addslashes($page_id);
 //--
	//GRAB MY CURRENT LFT + RGT
	//NOTE: I HAVE SQL WRAPPER THAT DOES THIS
	//"SELECT lft as m_lft,rgt as m_rgt 
	//FROM MY_PAGE_TABLE 
	//WHERE id='$page_id'";​
​
	//FIND MY WIDTH 
	$diff = intval($m_rgt) - intval($m_lft);
​
	//CALCULATE MY NEW LFT + RIGHT
	$new_left  = $p_lft+$offset;
	$new_right = $p_lft+$offset+$diff;
​
	//UDATE LFT + RGT
	//NOTE: I HAVE SQL WRAPPER THAT DOES THIS	
	//"UPDATE MY_PAGE_TABLE 
	//SET  "lft= '$new_left',rgt= '$new_right' 
	//WHERE id='$page_id';
​
	//CALCULATE OFFSET FOR NEXT LFT
	$offset = $offset + $diff + 1;​
}
​
//REBUILD PARENT
rebuild_tree($pid, $p_lft);

file: sort_preorder.txt

You don’t really need to set RGT ... if you run rebuild on parent, but it’s good knowledge to see how to do WIDTH ... you really just need to SET lft,lft+1, etc …

After I did this … i realized my original code could of been reused exactly, because I ran the rebuild…

.
//page_order is submitted valules
UPDATE TABLE MY_PAGE_TABLE
SET LFT = FIND\_IN_SET(id, $page_order)
​
//REBUILD PARENT
rebuild_tree($pid, $p_lft);

I am sorry I thought this was going to be simple to explain … ugh ... oh well it’s already written… and it was a great lesson learned for me.

 

comment

what they saidwho said it

it’s so chaotic!

2006-12-17
what's this?

It is chaotic thing to begin with … but more so a poorly written explanation… I’ll do better next time !

2006-12-18
DannyB

I don’t even know what you are talking about but the site looks great and you are updating regularly, so that’s a plus!

2006-12-20
Hayden

LOL ... yeah will do a better job my new years resolution… plus i got in this habit that i was trying to always go technical…

don’t think i will ever be as free flowing as you !

2006-12-20
DannyB

I once tried to explain How to build a heirarcy with one query
http://owensoft.net/v4/item/451/

2006-12-26
owen

Danny, thanks for the nice article. I’ve always wondered what this lgt, rgt stuff is all about.
Especially the first article, that you point at is brilliant. Understood it right away.
preorder tree traversal algorithm

excellent.

regards, marios

2007-09-01
Marios


note: you can only submit after you hit preview


nuff-respec is a weblog written by daniel bulli a senior web programmer in boston, ma.
more >

contact | resume | profile

recently :::

diversions :::

Using Flash And Staying Standards Compliant
Anyone who has ever worked with Flash on the web has likely come across the fact that embedding flash into a web page is usually no walk in the park...
A Design is Finished when...
This is probably the hardest part of designing for me.... 23 Pro designers weigh in with their opinions ...
JungleCrazy.com
Find all the Amazon.com products that are discounted by at least 70%
IETester
IETester is a free WebBrowser that allows you to have the rendering and javascript engines of IE8 beta 1, IE7 IE 6 and IE5.5 on Vista and XP, as well as the installed IE in the same process.
you still want more »