Re: pl/pgsql recursion/arrays (fwd)

From: Jason Tan <jason(at)rebel(dot)rebel(dot)net(dot)au>
To: Bo Lorentsen <bl(at)netgroup(dot)dk>
Cc: pgsql-novice(at)postgresql(dot)org
Subject: Re: pl/pgsql recursion/arrays (fwd)
Date: 2001-09-05 05:23:47
Message-ID: Pine.LNX.3.95.1010905143728.26091O-100000@rebel.rebel.net.au
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-novice

On Tue, 4 Sep 2001, Bo Lorentsen wrote:

> Jason Tan wrote:
>
> > I can tell you right now, it works.
>
> That's nice. Are you using the SETOF to make a list (then how do you append to
> it) or did you do something else to accumulate the array ?

No I am not what I did was used a different approach to the problem
because I wanted to solve it faster than I could find the relevant info.

I suspect what you would need to do is pass the array to the fucntion as a
parameter and at the top level call you would pass in an empty array.

I have included a description of the problem I wanted to solve and the
solution below, if you are interested in how I got around the problem
without retunring an array.

Regards
Jason

>
> > I have implemented a function that recurses through records that index on
> > each other in tree style.
>
> Funny thing, this is exactly the problem Im addressing to :-)
>
> > I think I have read all the latest offical doco, and dont recall seeing
> > that (SETOF) there.
>
> Hmm, I don't even remember from where I found this info.
>
> /BL
>

For general interest I will explain the probelm I wanted to solve and show
you my tables and function and the query I use.

To me the problem lends itself quite well to recurison.

The Problem
===========

The problem was I have a database to track people and orgnisations,
amongst other thigns.
People can belong to organisaitons.
They are teid together with a table, belongs_to.

Organisaitons can have sub organisations which are just other
organisations.
Each orgniasation has unique ID.
Each organisaiton has a parent_organisaiton which is either 0, for a
organisaiton that has no parent organisaion or the id of the parent
organisaion.

In this way a Company might exist say Acme Widgets, with a Support
Department which is further broken down into prodyuct support departments,
so teh Acme Widget Support Departmetn might have a Big Widget Support Team
and a Little Widget Support Team. In this model ACME Widgets, ACMEW
Widgets Support Dept, Big Widget Support Team and Little Widget Support
Team would all be organsiaitons. ACME WIdget would be a top level
organisaiton and the other orgs wiould be children(or grandchildren) of
ACME Widget.

I wanted to find all of the people who belonged to an organisaiton and all
of its child organisaitons.

For a variety of reasons, I did not want to use a nested loop and two
cursors to solve this problem in my application, so I wantedd to keep the
problem solution in the database or the SQL.

The Schema
==========

The relevant tables were:

contacts=# \d organisation
Table "organisation"
Attribute | Type | Modifier
---------------+--------------+--------------------
parent_org | integer | not null
org_id | integer | not null
org_type | integer | not null
org_name | varchar(256) | not null
short_name | varchar(256) |
last_modified | timestamp | not null
realm | integer | not null default 0
Indices: organisation_org_name_key,
organisation_pkey

contacts=# \d person
Table "person"
Attribute | Type | Modifier
---------------+-------------+--------------------
person_id | integer | not null
person_type | integer | not null
name | varchar(64) | not null
surname | varchar(64) | not null
middle_name | varchar(64) |
last_modified | timestamp | not null
realm | integer | not null default 0
Index: person_pkey

contacts=# \d belongs_to
Table "belongs_to"
Attribute | Type | Modifier
-----------+---------+--------------------
person_id | integer | not null
org_id | integer | not null
realm | integer | not null default 0
Index: belongs_to_pkey

The Query
=========
The query I use is:

select person_id, name, surname from person where person_id in
(select belongs_to_org(person_id,$org_id) from person )
order by surname;

The Function
============
The recursive PL/pgSQL function is definded as:
drop function belongs_to_org(int,int);

create function belongs_to_org(int,int) returns int as'
declare
result record;
child record;
retval person.person_id%type;
begin

--first off see if person_id belongs to org_id with asimpel query

select into result * from belongs_to where person_id=$1 and
org_id=$2;

if found then
return $1;
end if;

--if we did not return above then the person is not directly
associated
--with org_id, however they may be assocaited with a child
organisation
--of org, so we now try and find that out

for child in select * from organisation where parent_org = $2 loop

select into retval belongs_to_org($1,child.org_id);
if( retval != null) then
return retval;
end if;

end loop;

--last ditch if we got to heare then we dont match at all return
NULL
return NULL ;
end;
'language 'plpgsql';

--
------------------------------------------------------------------------------
Jason Tan jason(at)rebel(dot)net(dot)au
"Democracy is two wolves and a lamb voting on what to have for lunch.
Liberty is a well-armed lamb contesting the vote."
~Benjamin Franklin, 1759
------------------------------------------------------------------------------

In response to

Responses

Browse pgsql-novice by date

  From Date Subject
Next Message Oliver Elphick 2001-09-06 06:42:15 Re: avg() from multiple columns
Previous Message Jason Tan 2001-09-05 03:02:31 Re: avg() from multiple columns