Question

I am facing a scenario in which I have a foreign reference field of the same table and I need to get the list of values of such foreign references. For eg:

Field1 | Field2
----------------
X      |   Y
Y      |   Z
Z      |   A

Now I want to cascade select Field2 as in I want the output to be {Y,Z,A}.

Is there a way to achieve this?

Was it helpful?

Solution

I think SQL recursive queries is what you're searching for. Its syntax looks like this:

WITH RECURSIVE <cte_name> (column, ...) AS (
<non-recursive_term>
UNION ALL
<recursive_term>)
SELECT ... FROM <cte_name>;

In your case it will look like this:

  1. Create table and populate it:

    create table example (field1 char(1), field2 char(1));
    insert into example values ('X', 'Y');
    insert into example values ('Y', 'Z');
    insert into example values ('Z', 'A');
    select * from example;
    

    Result:

     field1 | field2 
     -------+--------
      X     | Y
      Y     | Z
      Z     | A
     (3 rows)
    
  2. Query:

     WITH RECURSIVE linked_example(list, first, last) AS (
       SELECT field1 || ', ' || field2, field1, field2 FROM example
       UNION ALL
       SELECT list || ', ' || field2, first, field2
         FROM
           linked_example, example
         WHERE
           last = field1
     )
     SELECT * from linked_example;
    

    Result:

         list    | first | last 
     ------------+-------+------
      X, Y       | X     | Y
      Y, Z       | Y     | Z
      Z, A       | Z     | A
      X, Y, Z    | X     | Z
      Y, Z, A    | Y     | A
      X, Y, Z, A | X     | A
     (6 rows)
    
  3. Now, just limit the query with WHERE clause:

     WITH RECURSIVE linked_example(list, first, last) AS (
       SELECT field1 || ', ' || field2, field1, field2 FROM example
       UNION ALL
       SELECT list || ', ' || field2, first, field2
         FROM
           linked_example, example
         WHERE
           last = field1
     )
     SELECT * from linked_example WHERE first = 'Y';
    

    Result:

       list   | first | last 
     ---------+-------+------
      Y, Z    | Y     | Z
      Y, Z, A | Y     | A
     (2 rows)
    

    As you can see, the last row is exactly what you want.

If you want more information and examples regarding SQL recursive queries, you can read my two articles covering this topic:

OTHER TIPS

You can achieve this simply using a jonction:

select a.field1, a.field2, b.field2
from my_table a
inner join my_table b
on a.field2 =b.field1

SQL FIddle sample

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top