If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

 
Go Back  dBforums > Database Server Software > DB2 > How to write recursive SQL with join? I am not sure it is even posible.

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old 11-03-06, 10:45
grofaty grofaty is offline
Registered User
 
Join Date: Jan 2003
Posts: 1,570
How to write recursive SQL with join? I am not sure it is even posible.

Hi,
I have one SQL problem, that I am not capable of solving. Any help is very appreciated. Below is an example of the problem.

Table1:
Code:
parent
-----------
          1
Table2:
Code:
parent      child
----------- -----------
          1           2
          2           3
          3           4
          5           6
          6           7
Rule 1: diplaying only those ancestors (from parent column) from table2 which has child, or grandchild or any other sub-level in table2 except the last level.
Sample (from table2): So "1" has child "2" and "2" has child "3" and "3" has child "4". So I would like to display data from parent column which is: "1", "2" and "3".

There is one more parent-child relationship in table2: parent "5" has child "6" and child "6" has child "7". So I would like to display data from parent column which is: "5" and "6".


Rule 2: I would like to display only those ancestor sub-level that has the matching row in table1.
Sample: There are two ancestors in table2: "1" and "5".
Result: "1"

The final result
So combining rule1 and rule2 there the final result is: "1", "2", "3".

Question: how to write such SQL? Is it possible to write it?


The SQL statements to prepare sample:
Code:
create table table1 (parent integer)
insert into table1 values (1)

create table table2 (child integer, parent integer)
insert into table2 values (1,2)
insert into table2 values (2,3)
insert into table2 values (3,4)
insert into table2 values (5,6)
insert into table2 values (6,7)
Thanks a lot,
Grofaty
Reply With Quote
  #2 (permalink)  
Old 11-03-06, 11:56
ARWinner ARWinner is offline
Registered User
 
Join Date: Jan 2003
Posts: 3,575
If I got what you want correctly, you basically want all the descendants of the ancestors in table1. If this is so, you do not need a join (although a join is valid for using in recursion). I have not tried this out, but it would look something like this:

with t1 (parent, child) as (
select * from table2 where parent in (select parent from table1)
union all
select * from table2, t1 where t2.parent = t1.child
) select * from t1

HTH

Andy
Reply With Quote
  #3 (permalink)  
Old 11-04-06, 03:11
grofaty grofaty is offline
Registered User
 
Join Date: Jan 2003
Posts: 1,570
ARWinner,
Quote:
Originally Posted by ARWinner
If I got what you want correctly, you basically want all the descendants of the ancestors in table1
That is correct.

Your suggestion returs error:
Code:
SQL0206N  "T2.PARENT" is not valid in the context where it is used.
SQLSTATE=42703
But I see there must be some other syntax errors in SQL for example: "select * from table2, t1 ", because t1 does not exist.

Any suggestions are very appreciated.
Thanks,
Grofaty

Last edited by grofaty; 11-04-06 at 03:44.
Reply With Quote
  #4 (permalink)  
Old 11-20-06, 08:11
ARWinner ARWinner is offline
Registered User
 
Join Date: Jan 2003
Posts: 3,575
Sorry for the delay, I was away on vacation. The only thing I can see wrong was i forgot the correlation from table2 to t2:

with t1 (parent, child) as (
select * from table2 where parent in (select parent from table1)
union all
select * from table2 as t2, t1 where t2.parent = t1.child
) select * from t1

t1 is the tablename of the common table expression of this recursive query.

Andy
Reply With Quote
  #5 (permalink)  
Old 11-21-06, 02:16
rahul_s80 rahul_s80 is offline
Registered User
 
Join Date: Jul 2006
Location: Pune , India
Posts: 433
Reply With Quote
  #6 (permalink)  
Old 11-21-06, 05:38
Wim Wim is offline
Registered User
 
Join Date: Nov 2004
Posts: 1,279
It's been a long time since I wrote my last recursive SQL script.

Perhaps http://www.dbforums.com/db2/1076604-how-pivot-dates-into-columns-printthread.html or to a lesser exted http://www.dbforums.com/archive/inde...t-1119101.html may help.
__________________
With kind regards . . . . . SQL Server 2000/2005/2008/2008 R2 Earned beers: 16
Wim
Beware of bugs in the above code; I have only proved it correct, not tried it. -- Donald Knuth
Grabel's Law: 2 is not equal to 3 -- not even for very large values of 2.
Pat Phelan's Law: 2 very definitely CAN equal 3 -- in at least two programming languages
Reply With Quote
  #7 (permalink)  
Old 11-21-06, 06:22
grofaty grofaty is offline
Registered User
 
Join Date: Jan 2003
Posts: 1,570
Quote:
Originally Posted by ARWinner
with t1 (parent, child) as (
select * from table2 where parent in (select parent from table1)
union all
select * from table2 as t2, t1 where t2.parent = t1.child
) select * from t1
The SQL returs error:
Quote:
SQL0421N The operands of a set operator or a VALUES clause do not have the
same number of columns. SQLSTATE=42826
As I see the first SQL is probably also not good:
"select * from table2 where parent in (select parent from table1)" it should be
"select * from table2 where child in (select parent from table1)".

Last edited by grofaty; 11-21-06 at 06:30.
Reply With Quote
  #8 (permalink)  
Old 11-21-06, 06:53
grofaty grofaty is offline
Registered User
 
Join Date: Jan 2003
Posts: 1,570
Hi,
the closes SQL I can write is (producing more records is better then less):
Quote:
select child from table2 where child in (select parent from table1)
union all
select b.child from table2 a, table2 b where a.parent=b.child
but this SQL produces result:
Quote:
CHILD
-----------
1
2
3
6
The 6 is incorrect! So the right answer should be:
Quote:
CHILD
-----------
1
2
3
Any idea how to eliminate number 6?
Reply With Quote
  #9 (permalink)  
Old 11-21-06, 08:18
ARWinner ARWinner is offline
Registered User
 
Join Date: Jan 2003
Posts: 3,575
This should work (I tested it):

with t1 (parent, child) as (
select * from table2 where parent in (select parent from table1)
union all
select t2.parent,t2.child from table2 as t2, t1 where t2.parent = t1.child
) select * from t1

Andy
Reply With Quote
  #10 (permalink)  
Old 11-24-06, 03:15
grofaty grofaty is offline
Registered User
 
Join Date: Jan 2003
Posts: 1,570
ARwinner,
my table2 is (parent int, child int)
your table2 is (child int, parent int)

so I have changed your SQL and final SQL looks like:
Code:
with t1 (parent,child) as (select * from table2 where child in 
(select parent from andy.tab1) union all select t2.child,t2.parent
 from table2 as t2, t1 where t2.child = t1.child) select * from t1
it looks like it is working...
Thanks a lot,
Grofaty

Last edited by grofaty; 11-24-06 at 03:33.
Reply With Quote
  #11 (permalink)  
Old 11-24-06, 03:39
grofaty grofaty is offline
Registered User
 
Join Date: Jan 2003
Posts: 1,570
Arwinner,
1. How to get only first column out of this SQL?
2. The result of your SQL is only part of the whole SQL I need to write (10 more tables involved and joined together with the result of your SQL) so how can I write:
select parent from (your_sql) from temp (temporaly table SQL)

It returs error:
Code:
SQL0104N  An unexpected token "AS" was found following "TH T1 (PARENT,CHILD)".
Expected tokens may include:  "JOIN".  SQLSTATE=42601
it looks like if 'with' sintax is used it can not be processed in temporary table anymore.
Thanks,
Grofaty
Reply With Quote
  #12 (permalink)  
Old 11-24-06, 08:14
ARWinner ARWinner is offline
Registered User
 
Join Date: Jan 2003
Posts: 3,575
To get only the first column back, just change

with t1 (parent,child) as (select * from table2 where child in
(select parent from andy.tab1) union all select t2.child,t2.parent
from table2 as t2, t1 where t2.child = t1.child)
select * from t1

to

with t1 (parent,child) as (select * from table2 where child in
(select parent from andy.tab1) union all select t2.child,t2.parent
from table2 as t2, t1 where t2.child = t1.child)
select parent from t1

All that changes is the last line. To retrieve fom other tables, just join to this select statement.

Andy
Reply With Quote
  #13 (permalink)  
Old 11-27-06, 03:45
grofaty grofaty is offline
Registered User
 
Join Date: Jan 2003
Posts: 1,570
ARWinner,
thank you very much. You helped med in a huge scale...
Grofaty
Reply With Quote
  #14 (permalink)  
Old 10-03-09, 05:37
ngavarta ngavarta is offline
Registered User
 
Join Date: Oct 2009
Posts: 1
Smile How about from Child travel back to all Parents?

How about from Child travel back to all Parents?

I'm able to do this by reversing the logic of the query, but it just return me 2 sets of same records, please help.
Reply With Quote
  #15 (permalink)  
Old 10-03-09, 17:35
ARWinner ARWinner is offline
Registered User
 
Join Date: Jan 2003
Posts: 3,575
Replying to a post that is about 3 years old and asking a vague question related to it will not get you much response. Please open a new thread, state your DB2 version and OS and explain what you want to do and what you tried, and maybe you will get some positive help.

Andy
Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On