473,472 Members | 1,702 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Recursing tree data in PL/pgSQL

Hi,

I've been scouring the net and reading the PostgreSQL docs for a while
now trying to learn how to create a recursive function in PL/pgSQL
that will return a whole subtree given a starting node. I wanted to
share my summary results here. Maybe this will help someone and save
them from doing a bunch of research (like I had to do :). For the
record, this is the first thing I've ever written in PL/pgSQL,
although I do have significant SQL experience. If any PostgreSQL
developers are reading this, you should implement a "CONNECT BY /
PRIOR" SQL command like Oracle does. It turns all this stuff into a
2-line SQL query. No extra functions needed.

In this proof-of-concept, I just did a lame table that has a node and
a parent which points back to another node in the same table. No
actual content. Also note the function overloading for the helper to
make it take just one argument. I'm passing a depth argument in this
example even though I don't use it. Again...proof-of-concept. The
depth of recursion is often useful to know. You can do LPAD()s to
indent your tree, for example.

One thing that's not immediately obvious if you've never done this:
RETURN NEXT is used to build up a return set, one row at a time. When
you're done, you RETURN and it returns the built-up set.

I did a few benchmarks on this data set. I wrote an equivalent
recursive function in PHP such that a new SQL query was issued on each
level of recursion. I "SELECT node, parent FROM tree WHERE parent =
$root" in PHP, and for each row I recurse on the PHP function. Bear in
mind this is a very small dataset (9 rows) and also that the database
and PHP are running on the same Linux 2.4.20 box. It would be
interesting to re-benchmark this with a much, much larger dataset.
Below is the ratio of execution time of PHP to SQL recursion on a few
trials.

Hope this helps someone,
Travis

PHP / SQL: 1.5631495206638
PHP / SQL: 1.488893156209
PHP / SQL: 1.8263854296389
PHP / SQL: 2.6210461029564
CREATE TABLE tree (node INTEGER, parent INTEGER);
INSERT INTO tree(node,parent) VALUES(1,0);
INSERT INTO tree(node,parent) VALUES(2,0);
INSERT INTO tree(node,parent) VALUES(3,1);
INSERT INTO tree(node,parent) VALUES(4,3);
INSERT INTO tree(node,parent) VALUES(5,4);
INSERT INTO tree(node,parent) VALUES(6,2);
INSERT INTO tree(node,parent) VALUES(7,6);
INSERT INTO tree(node,parent) VALUES(8,6);
INSERT INTO tree(node,parent) VALUES(9,2);

CREATE OR REPLACE FUNCTION getTree(INTEGER, INTEGER) RETURNS SETOF
tree AS '
DECLARE
root ALIAS FOR $1;
depth ALIAS FOR $2;
tempRow1 tree%ROWTYPE;
tempRow2 tree%ROWTYPE;
BEGIN
-- Using PostgreSQL 7.3.4.
-- Docs: http://www.postgresql.org/docs/7.3/static/plpgsql.html
-- See chapter 19, especially 19.6

FOR tempRow1 IN SELECT node, parent FROM tree WHERE parent = root
LOOP
RETURN NEXT tempRow1;
FOR tempRow2 IN SELECT node, parent FROM
getTree(tempRow1.node, depth+1) LOOP
RETURN NEXT tempRow2;
END LOOP;
END LOOP;
RETURN;
END;
' LANGUAGE 'plpgsql';

CREATE OR REPLACE FUNCTION getTree(INTEGER) RETURNS SETOF tree AS '
DECLARE
root ALIAS FOR $1;
tempRow tree%ROWTYPE;
BEGIN
FOR tempRow IN SELECT node, parent FROM getTree(root, 0) LOOP
RETURN NEXT tempRow;
END LOOP;
RETURN;
END;
' LANGUAGE 'plpgsql';

SELECT * FROM getTree(0);
node | parent
------+--------
1 | 0
3 | 1
4 | 3
5 | 4
2 | 0
6 | 2
7 | 6
8 | 6
9 | 2
(9 rows)

SELECT * FROM getTree(1);
node | parent
------+--------
3 | 1
4 | 3
5 | 4
(3 rows)

SELECT * FROM getTree(2);
node | parent
------+--------
6 | 2
7 | 6
8 | 6
9 | 2
(4 rows)
Jul 19 '05 #1
0 7146

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
by: Pete..... | last post by:
Hi all. I have made a webpage where there is a webform where people can fill in their personel information: The code is below: I want to transfer the data to a postgreSQL database ( I have...
4
by: projecktzero | last post by:
Well, I've managed to get an image into a postgre database, but now I'm having trouble getting it out. #! /usr/bin/env python from pyPgSQL import PgSQL def main(): connectdb =...
19
by: Christian Fowler | last post by:
I have a VERY LARGE pile of geographic data that I am importing into a database (db of choice is postgres, though may hop to oracle if necessary). The data is strictly hierarchical - each node has...
5
by: D. Dante Lorenso | last post by:
I have a simple table that I'd like to query to pull out a heirarchy from a tree relationship. What is the best way to do this without a 'CONNECT BY' clause like Oracle has? Example mytable...
19
by: snowdy | last post by:
I am using Interactive C with my handboard (68HC11) development system but I've got a problem that I am asking for help with. I am not new to C but learning all the time and I just cant see how to...
4
by: Tarique Jawed | last post by:
Alright I needed some help regarding a removal of a binary search tree. Yes its for a class, and yes I have tried working on it on my own, so no patronizing please. I have most of the code working,...
8
by: Steve Atkins | last post by:
I have an application where each user session opens and maintains a long-lived connection to the postgresql backend database. I need to keep a small amount of information (things like a unique...
2
by: elein | last post by:
When creating a new data type, what are the operators absolutely necessary for that type to particpate in a btree index? I know you need a "compare" that says = < or >= so does that mean that...
2
by: Gellert, Andre | last post by:
Hello, I have following problem: A user "xy" shouldn't have any rights to a table, but needs data from the content of the table. My idea was to setup a PL/PGSQL procedure to fetch the data...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
0
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.