Thread: Self Join Help
Im trying to figure out Self Joins with PostgreSQL. The output of the second SQL is correct, because of the where a.id = b.pid, but I would like to return all rows that are part of the tree. i.e. Foo Apache - PHP XHTML News - World News - Tech News Any help would be appreciated. Thanks. test=# select * from topics; id | pid | topicname ------------------+------------------+------------ AFAdDFoAPNX6wKbr | 0 | Foo AFAdDFoAPgTi9tAE | 0 | Apache AFAdDFoAPgTjCa4V | AFAdDFoAPgTi9tAE | PHP AFAdDFoAPlv1ENRn | 0 | XHTML AFAdDFoAPoSEWZaq | 0 | News AFAdDFoAPoSEaRPV | AFAdDFoAPoSEWZaq | World News AFAdDFoAPoSEee5_ | AFAdDFoAPoSEWZaq | Tech News (7 rows) test=# select a.topicname as parent, b.topicname as child from topics as a, topics as b where a.id = b.pid; parent | child --------+------------ Apache | PHP News | Tech News News | World News (3 rows)
Gerard Samuel wrote: > Im trying to figure out Self Joins with PostgreSQL. The output of the > second SQL is correct, because of the where a.id = b.pid, > but I would like to return all rows that are part of the tree. > test=# select * from topics; > id | pid | topicname > ------------------+------------------+------------ > AFAdDFoAPNX6wKbr | 0 | Foo > AFAdDFoAPgTi9tAE | 0 | Apache > AFAdDFoAPgTjCa4V | AFAdDFoAPgTi9tAE | PHP > AFAdDFoAPlv1ENRn | 0 | XHTML > AFAdDFoAPoSEWZaq | 0 | News > AFAdDFoAPoSEaRPV | AFAdDFoAPoSEWZaq | World News > AFAdDFoAPoSEee5_ | AFAdDFoAPoSEWZaq | Tech News > (7 rows) > > test=# select a.topicname as parent, b.topicname as child from topics as > a, topics as b where a.id = b.pid; > parent | child > --------+------------ > Apache | PHP > News | Tech News > News | World News > (3 rows) do you mean return also root nodes? You could just add insert into topics (id, topicname) values (0, 'root'); and then you should be getting test=# select a.topicname as parent, b.topicname as child from topics as a, topics as b where a.id = b.pid; parent | child --------+------------ root | Apache root | News root | Foo root | XHTML Apache | PHP News | Tech News News | World News or, if you dont want to add a ficticious root node you could do a left join (if you can do left self joins, dont see a reason why not, but never did it): test=# select a.topicname as parent, b.topicname as child from topics as a left join topics as b on a.id = b.pid; parent | child --------+------------ XHTML | null Foo | null Apache | PHP News | Tech News News | World News but then, your self referencing querry starts going into the idea of recursive select statements. I have little knowledge in this, MS-SQL does not have true recursive selects (you can string up bunch of left joins, but its a workaround hack). Oracle and I think db2 do support recursive selects, but only to a certain level (Oracle recurses up to 32levels I think), I wouldnt mind hearing how recursive Select would work in your case: by recursive I mean I want to select all nodes who have a specific node above the tree (be it parent/grand parent/ grand grand parent, etc). /apz, If your aim in life is nothing, you can't miss.
this is second time I post to a forum, and second time I correct myself... ugh, I should delay posting by 15 minutes, or stop re-reading my emails after posting... ;D anyways: apz wrote: > test=# select a.topicname as parent, b.topicname as child from topics as > a left join topics as b on a.id = b.pid; > > parent | child > --------+------------ > XHTML | null > Foo | null > Apache | PHP > News | Tech News > News | World News this actually should return: test=# select a.topicname as parent, b.topicname as child from topics as a left join topics as b on a.id = b.pid; parent | child ------------+------------ XHTML | null Foo | null Apache | PHP News | Tech News News | World News PHP | null Tech News | null World News | null the querry with left join should return child=null if a node is a leaf. so XHTML and PHP return child as null because neither have any nodes underneath. this also should mean that topicname should not allow null values, not to confuse ourselves further on. so two ways are: - add one node which is always root, use your querry - use left join, when no child then child returns as null /apz, You can always tell luck from ability by its duration.
Thanks for you help thus far. The final goal would be to achieve results like -> parent | child ------------+------------ Foo | Apache | PHP XHTML | News | Tech News News | World News Im playing with the SQL to see if its possible, but any insight would be appreciated. Thanks again. apz wrote: > this is second time I post to a forum, and second time I correct > myself... ugh, I should delay posting by 15 minutes, or stop > re-reading my emails after posting... ;D > > anyways: > > apz wrote: > >> test=# select a.topicname as parent, b.topicname as child from topics >> as a left join topics as b on a.id = b.pid; >> >> parent | child >> --------+------------ >> XHTML | null >> Foo | null >> Apache | PHP >> News | Tech News >> News | World News > > > this actually should return: > > > test=# select a.topicname as parent, b.topicname as child from topics as > a left join topics as b on a.id = b.pid; > > parent | child > ------------+------------ > XHTML | null > Foo | null > Apache | PHP > News | Tech News > News | World News > PHP | null > Tech News | null > World News | null > > > the querry with left join should return child=null if a node is a leaf. > so XHTML and PHP return child as null because neither have any nodes > underneath. > this also should mean that topicname should not allow null values, not > to confuse ourselves further on. > > so two ways are: > - add one node which is always root, use your querry > - use left join, when no child then child returns as null > > > > /apz, You can always tell luck from ability by its duration. > > > ---------------------------(end of broadcast)--------------------------- > TIP 6: Have you searched our list archives? > > http://archives.postgresql.org > >
Presto -> select a.topicname as parent, b.topicname as child from topics as a left join topics as b on a.id = b.pid where a.pid = 0; parent | child --------+------------ Foo | Apache | PHP XHTML | News | World News News | Tech News (5 rows) Thanks for pointing me in the right direction.... Gerard Samuel wrote: > Thanks for you help thus far. > The final goal would be to achieve results like -> > parent | child > ------------+------------ > Foo | > Apache | PHP > XHTML | > News | Tech News > News | World News > > Im playing with the SQL to see if its possible, but any insight would > be appreciated. > Thanks again. > > apz wrote: > >> this is second time I post to a forum, and second time I correct >> myself... ugh, I should delay posting by 15 minutes, or stop >> re-reading my emails after posting... ;D >> >> anyways: >> >> apz wrote: >> >>> test=# select a.topicname as parent, b.topicname as child from >>> topics as a left join topics as b on a.id = b.pid; >>> >>> parent | child >>> --------+------------ >>> XHTML | null >>> Foo | null >>> Apache | PHP >>> News | Tech News >>> News | World News >> >> >> >> this actually should return: >> >> >> test=# select a.topicname as parent, b.topicname as child from topics as >> a left join topics as b on a.id = b.pid; >> >> parent | child >> ------------+------------ >> XHTML | null >> Foo | null >> Apache | PHP >> News | Tech News >> News | World News >> PHP | null >> Tech News | null >> World News | null >> >> >> the querry with left join should return child=null if a node is a leaf. >> so XHTML and PHP return child as null because neither have any nodes >> underneath. >> this also should mean that topicname should not allow null values, >> not to confuse ourselves further on. >> >> so two ways are: >> - add one node which is always root, use your querry >> - use left join, when no child then child returns as null >> >> >> >> /apz, You can always tell luck from ability by its duration. >> >> >> ---------------------------(end of broadcast)--------------------------- >> TIP 6: Have you searched our list archives? >> >> http://archives.postgresql.org >> >> > > > ---------------------------(end of broadcast)--------------------------- > TIP 6: Have you searched our list archives? > > http://archives.postgresql.org > >