Recursive subquery

I have a table with origin and destination ids.
There can be a dynamic number of connections ( not expecting more than 5) and the relation is always one to one: A -->B-->C-->D
A or B or C or D can only apear in a relation, This mean A-->C cannot happen because A e already connected to B.
I want to create a querie that receives the last destination values and return a column with the origin values that are related with that value:
for example:
if my parameter value is D, my result will be a column with three rows : A,B,C
if my parameter value is C, my result will be a column with two rows : A,B
example:
create table test_list as (
select 32000 origin, 68200 destination from dual
union all
select 60000 origin, 168200 destination from dual
union all
select 8200 origin, 36600 destination from dual
union all
select 36600 origin, 8400 destination from dual
union all
select 8400 origin, 61800 destination from dual
)I tried conect by prior and connect by root but could not achieve it!
found also some articles about "Recursive Subquery Factoring" but that got even worst because I could not get it to work.
My database is "Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production"
SELECT origin   from test_list  where
    origin in (select *  FROM (
     SELECT CONNECT_BY_ROOT destination
      FROM test_list
    CONNECT BY PRIOR origin = destination and destination =68200 )
)So in my list:
32000 connects to 68200
60000 connects to 168200
8200 connects to 36600
36600 connects to 8400
8400 connects to 61800
My expected results are:
If parameter "VALUE_TO_SEARCH" = 68200 I expect only: 32000
If parameter "VALUE_TO_SEARCH" = 168200 I expect only: 60000
If parameter "VALUE_TO_SEARCH" = 61800 I expect : 8400,36600,8200
If parameter "VALUE_TO_SEARCH" = 32000 I expect no results.
What should be the best method to use, for best performance and in case is with the CONNECT_BY_ROOT and " CONNECT BY PRIOR" what am I doing wrong there?
Best regards,
Ricardo Tomás

Use START WITH clause:
SQL> select * from test_list;
    ORIGIN DESTINATION
     32000       68200
     60000      168200
      8200       36600
     36600        8400
      8400       61800
SQL> select  origin
  2    from  test_list
  3    start with destination = &destination
  4    connect by destination = prior origin
  5  /
Enter value for destination: 68200
old   3:   start with destination = &destination
new   3:   start with destination = 68200
    ORIGIN
     32000
SQL> /
Enter value for destination: 168200
old   3:   start with destination = &destination
new   3:   start with destination = 168200
    ORIGIN
     60000
SQL> /
Enter value for destination: 61800
old   3:   start with destination = &destination
new   3:   start with destination = 61800
    ORIGIN
      8400
     36600
      8200
SQL> /
Enter value for destination: 32000
old   3:   start with destination = &destination
new   3:   start with destination = 32000
no rows selected
SQL> SY.

Similar Messages

  • Recursive WITH (Recursive Subquery Factoring) Never Returns

    11.2.0.2 database on Windows, SQL Developer Version 3.2.20.09, build MAIN-09.87 (Database and SQL Developer are on the same machine. I have also tried connecting to a Linux 11.2 database and have the same results.)
    I've been doing some simple testing with recursive WITH (Recursive Subquery Factoring) and when I run this following statement in SQL*Plus it returns instantly. However when running in SQL Developer it never returns, I've let it run for quite a long time (172 seconds) and gotten nothing, I finally kill the statement. Once I ran it and even killing the job didn't come back. I can get an explain plan but if I try to run it, run as script or autotrace it never returns. I have only one plan in the plan_table for this test, and it's only 4 lines long. No errors, no messages.
    WITH get_plan (query_plan, id, planlevel) as
    select ' '||operation||' '||options||' '||object_name query_plan, id, 1 planlevel
    from plan_table
    where id = 0
    union all
    select lpad(' ',2*planlevel)||p.operation||' '||p.options||' '||p.object_name query_plan, p.id, planlevel+1
    from get_plan g, plan_table p
    where g.id = p.parent_id
    SELECT QUERY_PLAN FROM GET_PLAN ORDER BY PLANLEVEL;

    Hi Jeff, using either give the same results. The query is "running", as is the little graphic with the bouncing gray bar is moving back and forth saying either "Query Results" or "Scriptrunner Task" as appropriate.
    OK this is odd. I run a count(*) on plan_table in SQL*Plus and get 4, in SQL Developer I get 487. Hun? That makes no sense I'm connect as the same user in each. Where are all these other entries coming from and why can't I see them in SQL Plus? Does SQL Developer have it's own PLAN_TABLE?
    **EDIT --- Yes that seems to be the case. The PLAN_ID I see in SQL Plus doesn't even exist in the SQL Deveropler version of the table. OK that's good to know. I assume the plan_table for SQL Developer is local to it somehow? It's not in the database as best I can see.
    Edited by: Ric Van Dyke on Feb 7, 2013 5:19 PM

  • Recursive subquery factoring datatypes?

    Hi all,
    using 11.2.0.2.0
    just mucking around with Recursive Subquery Factoring, trying to get my head around it.
    I can do this fine:
    SQL> with numlist (num) AS (SELECT 1 num
      2                          from dual
      3                          UNION ALL
      4                          SELECT numlist.num + 1
      5                            FROM numlist
      6                          where numlist.num < 10)
      7  SELECT *
      8    from numlist;
           NUM
             1
             2
             3
             4
             5
             6
             7
             8
             9
            10
    10 rows selected.but not with dates:
    SQL> WITH datelist (dte) AS (SELECT to_date('01-01-2011','dd-mm-yyyy') Dte
      2                   FROM dual
      3                 UNION ALL
      4                 SELECT datelist.dte + 1
      5                   FROM datelist
      6                  WHERE datelist.dte < trunc(SYSDATE))
      7  select *
      8    from datelist;
                   SELECT datelist.dte + 1
    ERROR at line 4:
    ORA-01790: expression must have same datatype as corresponding expressionI'm not sure what I need to do.....
    I'm sure it's a fairly straightforward

    Hemant K Chitale wrote:
    I don't have an 11.2.0 environment to test this.
    Try with a CAST at line 4 ? CAST X.DTE to a Date ?
    Hemant K Chitaleahh, that's a little bit better.... it seems a little bit funky though:
    15:38:58 SQL> WITH x (dte) AS (SELECT cast (to_date('01-01-2011','dd-mm-yyyy') as date) Dte
    15:39:02   2                   FROM dual
    15:39:02   3                 UNION ALL
    15:39:02   4                 SELECT cast(x.dte + 1 as date)
    15:39:02   5                   FROM x
    15:39:02   6                  WHERE x.dte < to_date('01-02-2011','dd-mm-yyyy'))
    15:39:02   7  select *
    15:39:02   8    from x;
    DTE
    01-JAN-11
    31-DEC-10
    30-DEC-10
    29-DEC-10
    28-DEC-10
    27-DEC-10
    26-DEC-10
    25-DEC-10
    24-DEC-10
    23-DEC-10
    22-DEC-10
    21-DEC-10
    20-DEC-10
    19-DEC-10
    18-DEC-10
    17-DEC-10
    16-DEC-10
    15-DEC-10
    14-DEC-10
    13-DEC-10
    12-DEC-10
    11-DEC-10
    10-DEC-10
    09-DEC-10
    08-DEC-10
    07-DEC-10
    06-DEC-10
    05-DEC-10
    04-DEC-10
    03-DEC-10
    02-DEC-10
    01-DEC-10
    30-NOV-10
    29-NOV-10
    28-NOV-10
    27-NOV-10
    26-NOV-10
    25-NOV-10
    24-NOV-10
    23-NOV-10
    22-NOV-10
    21-NOV-10
    20-NOV-10
    ...looks like it's going backwards.
    if I cast it like the below, it only gives me one record...
    15:39:03 SQL> WITH x (dte) AS (SELECT cast (to_date('01-01-2011','dd-mm-yyyy') as date) Dte
    15:40:52   2                   FROM dual
    15:40:52   3                 UNION ALL
    15:40:52   4                 SELECT cast(x.dte as date) + 1
    15:40:52   5                   FROM x
    15:40:52   6                  WHERE x.dte < to_date('01-02-2011','dd-mm-yyyy'))
    15:40:52   7  select *
    15:40:52   8    from x;
    DTE
    01-JAN-11
    1 row selected.This is bizarre....

  • Analitical functions in recursive subquery factoring

    Hi,
    I have a problem with analitical functions in recursive subquery factoring.
    My version:
    >
    BANNER
    Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
    PL/SQL Release 11.2.0.1.0 - Production
    CORE     11.2.0.1.0     Production
    TNS for 64-bit Windows: Version 11.2.0.1.0 - Production
    NLSRTL Version 11.2.0.1.0 - Production
    >
    When I run following query it runs fine:
    with a (num, total) as
    (select
      1 num
      ,1 total
    from
      dual
    union all
    select
      num + 1             num
      ,total + num + 1    total
    from
      a
    where
      num < 10
    select
    from
      a
    NUM TOTAL
      1     1
      2     3
      3     6
      4    10
      5    15
      6    21
      7    28
      8    36
      9    45
    10    55
    10 rows selected When I run the following query it generates an error:
    with a (num, total) as
    (select
      1 num
      ,1 total
    from
      dual
    union all
    select
      num + 1             num
      ,sum(num) over ()    total
    from
      a
    where
      num < 10
    select
    from
      a
    Error:
    ORA-32486: unsupported operation in recursive branch of recursive WITH clause The manual states:
    >
    Oracle® Database
    SQL Language Reference
    11g Release 2 (11.2)
    E17118-04
    October 2010
    The recursive member cannot contain any of the following elements:
    - The DISTINCT keyword or a GROUP BY clause
    - The model_clause
    - An aggregate function. However, analytic functions are permitted in the select list.
    - Subqueries that refer to query_name.
    - Outer joins that refer to query_name as the right table.
    >
    According to this it should be posible to have an analitical function in here.
    Also on this form I see samples of it used as such.
    eg.:
    Re: Seat Distribution-Can we do this in SQL?
    Can anybody tell me if this is a problem with my version of oracle?
    Or is there some other problem here?
    Thanks,
    Peter

    Works ok in 11.2.0.3
    SQL> select * from v$version;
    BANNER
    Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
    PL/SQL Release 11.2.0.3.0 - Production
    CORE    11.2.0.3.0      Production
    TNS for 64-bit Windows: Version 11.2.0.3.0 - Production
    NLSRTL Version 11.2.0.3.0 - Production
    SQL> with a (num, total) as
      2  (select
      3    1 num
      4    ,1 total
      5  from
      6    dual
      7  union all
      8  select
      9    num + 1             num
    10    ,sum(num) over ()    total
    11  from
    12    a
    13  where
    14    num < 10
    15  )
    16  select
    17    *
    18  from
    19    a
    20  ;
           NUM      TOTAL
             1          1
             2          1
             3          2
             4          3
             5          4
             6          5
             7          6
             8          7
             9          8
            10          9
    10 rows selected.

  • PARTITION RANGE SUBQUERY - Access path

    Below quote is from Oracle product documentation.
    <quote>
    If the table with the WHERE predicate is relatively small compared to the partitioned table, and the expected reduction of records or partitions for the partitioned table is significant, Oracle will perform dynamic partition pruning using a recursive subquery
    </quote>
    http://download.oracle.com/docs/cd/B19306_01/server.102/b14223/parpart.htm#sthref215
    create table t(
         x number,
         y number,
         z number
    ) partition by range(z)
         partition p_10 values less than ( 11),
         partition p_20 values less than ( 21),
         partition p_30 values less than ( 31),
         partition p_40 values less than ( 41),
         partition p_50 values less than ( 51),
         partition p_60 values less than ( 61),
         partition p_70 values less than ( 71),
         partition p_80 values less than ( 81),
         partition p_90 values less than ( 91),
         partition p_100 values less than ( 101)
    create table t1
    as
    select mod(rownum,10) as id,
         username ,
         sysdate as dt
    from all_users;     
    insert /*+ append */ into t
    select level,level,10
    from dual
    connect by level <= 1000000;
    commit;
    insert /*+ append */ into t select x,y,20 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,30 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,40 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,50 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,60 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,70 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,80 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,90 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,100 from t partition (p_10);
    commit;
    begin
         dbms_stats.gather_table_Stats(user,'T1');
         dbms_stats.gather_table_stats(ownname=>user,tabname=>'T',degree=>16);
    end;
    select /*+ use_hash(t,t1) */ t.*
    from t, t1
    where t.z = t1.id
    and t1.username ='SCOTT'
    call count cpu elapsed disk query current rows
    Parse 1 0.03 0.67 0 0 0 0
    Execute 1 0.00 0.00 0 0 0 0
    Fetch 1 0.65 0.65 0 2507 0 0
    total 3 0.68 1.32 0 2507 0 0
    Misses in library cache during parse: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: 100
    Rows Row Source Operation
    0 HASH JOIN (cr=2510 pr=0 pw=0 time=653031 us)
    1 TABLE ACCESS FULL T1 (cr=3 pr=0 pw=0 time=59 us)
    1000000 PARTITION RANGE SUBQUERY PARTITION: KEY(SUBQUERY) KEY(SUBQUERY) (cr=2507 pr=0 pw=0 t
    1000000 TABLE ACCESS FULL T PARTITION: KEY(SUBQUERY) KEY(SUBQUERY) (cr=2504 pr=0 pw=0 t
    select /*+ use_nl(t,t1) */ t.*
    from t, t1
    where t.z = t1.id
    and t1.username ='SCOTT'
    call count cpu elapsed disk query current rows
    Parse 1 0.00 0.00 0 0 0 0
    Execute 1 0.00 0.00 0 0 0 0
    Fetch 1 0.12 0.12 0 2506 0 0
    total 3 0.12 0.12 0 2506 0 0
    Misses in library cache during parse: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: 100
    Rows Row Source Operation
    0 NESTED LOOPS (cr=2506 pr=0 pw=0 time=123836 us)
    1 TABLE ACCESS FULL T1 (cr=3 pr=0 pw=0 time=53 us)
    0 PARTITION RANGE ITERATOR PARTITION: KEY KEY (cr=2503 pr=0 pw=0 time=123777 us)
    0 TABLE ACCESS FULL T PARTITION: KEY KEY (cr=2503 pr=0 pw=0 time=123761 us)
    Questions_
    1) what is the significant in having this PARTITION RANGE SUBQUERY access path in Oracle 10g? Even reading documentation, still unclear.
    Edited by: Rajeshwaran on Nov 15, 2010 8:05 AM

    Yep..Here is the code.
    create table t(
         x number,
         y number,
         z number
    ) partition by range(z)
         partition p_10 values less than ( 11),
         partition p_20 values less than ( 21),
         partition p_30 values less than ( 31),
         partition p_40 values less than ( 41),
         partition p_50 values less than ( 51),
         partition p_60 values less than ( 61),
         partition p_70 values less than ( 71),
         partition p_80 values less than ( 81),
         partition p_90 values less than ( 91),
         partition p_100 values less than ( 101)
    create table t1
    as
    select mod(rownum,10) as id,
            username ,
            sysdate as dt
    from all_users;       
    insert /*+ append */ into t
    select level,level,10
    from dual
    connect by level <= 1000000;
    commit;
    insert /*+ append */ into t select x,y,20 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,30 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,40 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,50 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,60 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,70 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,80 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,90 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,100 from t partition (p_10);
    commit;
    begin
         dbms_stats.gather_table_Stats(user,'T1');
         dbms_stats.gather_table_stats(ownname=>user,tabname=>'T',degree=>16);
    end;
    select /*+ use_hash(t,t1) */ t.*
    from t, t1
    where t.z = t1.id
    and   t1.username ='SCOTT'
    call     count       cpu    elapsed       disk      query    current        rows
    Parse        1      0.03       0.67          0          0          0           0
    Execute      1      0.00       0.00          0          0          0           0
    Fetch        1      0.65       0.65          0       2507          0           0
    total        3      0.68       1.32          0       2507          0           0
    Misses in library cache during parse: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: 100 
    Rows     Row Source Operation
          0  HASH JOIN  (cr=2510 pr=0 pw=0 time=653031 us)
          1   TABLE ACCESS FULL T1 (cr=3 pr=0 pw=0 time=59 us)
    1000000   PARTITION RANGE SUBQUERY PARTITION: KEY(SUBQUERY) KEY(SUBQUERY) (cr=2507 pr=0 pw=0 t
    1000000    TABLE ACCESS FULL T PARTITION: KEY(SUBQUERY) KEY(SUBQUERY) (cr=2504 pr=0 pw=0 t
    select /*+ use_nl(t,t1) */ t.*
    from t, t1
    where t.z = t1.id
    and   t1.username ='SCOTT'
    call     count       cpu    elapsed       disk      query    current        rows
    Parse        1      0.00       0.00          0          0          0           0
    Execute      1      0.00       0.00          0          0          0           0
    Fetch        1      0.12       0.12          0       2506          0           0
    total        3      0.12       0.12          0       2506          0           0
    Misses in library cache during parse: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: 100 
    Rows     Row Source Operation
          0  NESTED LOOPS  (cr=2506 pr=0 pw=0 time=123836 us)
          1   TABLE ACCESS FULL T1 (cr=3 pr=0 pw=0 time=53 us)
          0   PARTITION RANGE ITERATOR PARTITION: KEY KEY (cr=2503 pr=0 pw=0 time=123777 us)
          0    TABLE ACCESS FULL T PARTITION: KEY KEY (cr=2503 pr=0 pw=0 time=123761 us)

  • Querying all_tab_columns

    Hi all,
    This is a "my query takes too long" question but it relates to the ALL_TAB_COLUMNS view.
    I'm trying to generate some basic DML scripts from a large number of tables (insert/update) the cheating way by selecting columns from all_tab_columns
    e.g.
    select 'insert into '||table_name||' ('
      from all_tables
    where table_name = 'TABLE_NAME_HERE'
    union all
    select column_name||','
      from all_tab_columns
    where table_name = 'TABLE_NAME_HERE'
    --etc.however, I want the column names all on one line.
    so I have the following, which I imagine should create the column_name's on one line but it "runs for ages"
    select sys_connect_by_path(column_name,', ') c
      from all_tab_columns
    where owner = 'WHITEHAT'
       and table_name = 'FOO'
       and connect_by_isleaf = 1
       start with column_id = 1
       connect by column_id = prior column_id + 1I am using 10gR2 so unfortunately I can't use recursive subquery factoring just yet, although that equivalent runs quickly as expected on our 11g environment:
    with t (column_name, column_id)
                 as (select cast(column_name as varchar2(4000)), column_id
                       from all_tab_columns
                      where owner = 'WHITEHAT'
                        and table_name = 'FOO'
                        and column_id = 1
                      UNION ALL
                      SELECT cast(t.column_name||', '||atc.column_name as varchar2(4000))
                            ,atc.column_id
                        from t
                            ,all_tab_columns atc
                       where owner = 'WHITEHAT'
                        and table_name = 'FOO'
                        and atc.column_id = t.column_id + 1
    select column_name
      from (
             select column_name, column_id, max(column_id) over () max_col_id
             from t          
    where column_id = max_col_idwhat am I doing wrong?

    Hi,
    WhiteHat wrote:
    ... so I have the following, which I imagine should create the column_name's on one line but it "runs for ages"
    select sys_connect_by_path(column_name,', ') c
    from all_tab_columns
    where owner = 'WHITEHAT'
    and table_name = 'FOO'
    and connect_by_isleaf = 1
    start with column_id = 1
    connect by column_id = prior column_id + 1... what am I doing wrong?The WHERE clause is applied after the START WITH and CONNECT BY clauses are complete.
    So you're starting with one row from every table. Let's say you have a small database, with 1000 tables. On LEVEL=1 you have 1000 rows. Then you're connecting every column with column_id=2 to each of those those 1000 rows. Almost every table will have a column with column_id=2, so you'll have 1,000,000 rows on LEVEL=2. I think you can see where this is going.
    Don't use a WHERE clause to get the right table. Put the conditions you now have in the WHERE clause (or equivalent conditions, except for "connect_by_isleaf = 1") in the START WITH and CONNECT BY clauses, instead, or apply the WHERE clause in a sub-query, first, like this:
    WITH     universe     AS
         SELECT     column_name
         ,     column_id
         FROM     all_tab_columns
         WHERE     owner          = 'WHITEHAT'
         AND     table_name     = 'FOO'
    SELECT     SYS_CONNECT_BY_PATH (column_name, ',')     AS c
    FROM     universe
    WHERE     CONNECT_BY_ISLEAF     = 1
    START WITH     column_id     = 1
    CONNECT BY     column_id     = 1 + PRIOR column_id
    ;

  • What is "with"   and "Connecty By" in Oracle SQL

    Hello All,
    I'm Just going through the forum topics, I have seen sql queries starts like "with t as" and at the end it closes like "connect ". I have seen this kind for normal queries also. Please let me know what is the "with" concept and when do we use that?
    Thanks in Advance!!!

    And in 11gR2 you can combine the two with the new feature Recursive Subquery Refactoring (well sort of, because you don't need the connect by bit)
    I'd link to the official docs but they seem to be suffering intermittent issues at the moment so:
    http://technology.amis.nl/blog/6267/oracle-rdbms-11gr2-new-style-hierarchical-querying-using-recursive-subquery-factoring
    http://technology.amis.nl/blog/6104/oracle-rdbms-11gr2-goodbye-connect-by-or-the-end-of-hierarchical-querying-as-we-know-it

  • SQL query, generating several rows by a value in a field

    I am using Oracle database. Imaging I have a table with a row as following
         col1  |  col2  | col3
        'Str1' | 'Str2' | 4
    The value from col3=4 should generate 4 rows as following:
         col1  |  col2  | col3
        'Str1' | 'Str2' | 1
        'Str1' | 'Str2' | 2
        'Str1' | 'Str2' | 3
        'Str1' | 'Str2' | 4
    After several hours in front of the screen and stil no luck - how can I create such a select query???

    You're mixing up the 'standard' WITH clause and Recursive Subquery Factoring (which NEEDS a UNION ALL)  (see: http://docs.oracle.com/cd/E11882_01/server.112/e26088/statements_10002.htm#i2129904).
    This should work on 10.2:
    SQL> select * from v$version;
    BANNER
    Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
    PL/SQL Release 10.2.0.4.0 - Production
    CORE    10.2.0.4.0      Production
    TNS for Linux: Version 10.2.0.4.0 - Production
    NLSRTL Version 10.2.0.4.0 - Production
    SQL> with t as (select 'str1' col1, 'str2' col2, 4 col3 from dual
      2            )
      3  select col1
      4  ,      col2
      5  ,      level col3
      6  from   t
      7  connect by level <= col3;
    COL1 COL2       COL3
    str1 str2          1
    str1 str2          2
    str1 str2          3
    str1 str2          4
    See here as well: http://technology.amis.nl/2009/09/01/oracle-rdbms-11gr2-goodbye-connect-by-or-the-end-of-hierarchical-querying-as-we-know-it/

  • What is API? Why we use in oracle Apps? Please explain me little bit.

    Hi,
    Can you please explain me step by step for what is API. why we use and where we have to use? please explain me.
    Regards,
    Raj

    And in 11gR2 you can combine the two with the new feature Recursive Subquery Refactoring (well sort of, because you don't need the connect by bit)
    I'd link to the official docs but they seem to be suffering intermittent issues at the moment so:
    http://technology.amis.nl/blog/6267/oracle-rdbms-11gr2-new-style-hierarchical-querying-using-recursive-subquery-factoring
    http://technology.amis.nl/blog/6104/oracle-rdbms-11gr2-goodbye-connect-by-or-the-end-of-hierarchical-querying-as-we-know-it

  • Inverse of count

    I have the below data set -
    Order_id Item Qty
    1 A1 3
    2 A2 2
    3 A3 3
    My desired output (With only one SQL query) is mentioned below-
    Order_id Item Qty
    1 A1 1
    1 A1 1
    1 A1 1
    2 A2 1
    2 A2 1
    3 A3 1
    3 A3 1
    3 A3 1
    How do I do this?

    Another way would be :
    SQL> with sample_data as (
      2   select 1 order_id, 'A1' item, 3 qty from dual union all
      3   select 2, 'A2', 2 from dual union all
      4   select 3, 'A3', 3 from dual
      5  )
      6  select t1.order_id
      7       , t1.item
      8       , t2.column_value as qty
      9  from sample_data t1
    10     , table(
    11         cast(
    12           multiset(
    13             select 1 from dual connect by level <= t1.qty
    14           ) as sys.odcinumberlist
    15         )
    16       ) t2
    17  ;
      ORDER_ID ITEM        QTY
             1 A1            1
             1 A1            1
             1 A1            1
             2 A2            1
             2 A2            1
             3 A3            1
             3 A3            1
             3 A3            1
    8 rows selected
    or, using recursive subquery factoring (11.2) :
    SQL> with sample_data as (
      2   select 1 order_id, 'A1' item, 3 qty from dual union all
      3   select 2, 'A2', 2 from dual union all
      4   select 3, 'A3', 3 from dual
      5  ),
      6  dataset (order_id, item, qty, sofar) as
      7  (
      8    select order_id
      9         , item
    10         , qty
    11         , 1
    12    from sample_data
    13    union all
    14    select order_id, item, qty, sofar+1
    15    from dataset
    16    where sofar < qty
    17  )
    18  search depth first by order_id set seq
    19  select order_id, item, 1 as qty
    20  from dataset
    21  ;
      ORDER_ID ITEM        QTY
             1 A1            1
             1 A1            1
             1 A1            1
             2 A2            1
             2 A2            1
             3 A3            1
             3 A3            1
             3 A3            1
    8 rows selected

  • Order of the output

    I have a query
    Eg: select id,name from user
    where user.id in ('a7','a6','a3',....); --- ID's are in different order not, in ascending or descending
    the output of the above query is something like
    id name
    a3 a3_name
    a7 a7_name
    a6 a6_name
    But I would like the output to be in the order input was given inside
    a7 a7_name
    a6 a6_name
    a3 a3_name
    How do we do this?

    user651347 wrote:
    I had a list given with 300 users and neither in ASC or DESC order
    so we need to order this the way it was given or in the select ... in (); statementOk. Did you mathematical "set" theory at school? Familiar with Venn diagrams?
    If you are, let's look at two sets of values.... (1,2,3,4) and (4,3,2,1)....
    As a Venn diagram you'd end up drawing those two sets as:-
    Set A                                             Set B
    #                    #   2  #                     #
    #                    #  1     #                     #
    #                    #   4    #                     #
    #                    #   3  #                     #
                #######               #######They are identical sets and there is no order to them.
    You can even do this in SQL, to see if there is a difference in the two sets...
    SQL> create or replace type myset as table of number;
      2  /
    Type created.
    SQL> select myset(1,2,3,4) multiset except myset(4,3,2,1) as diff from dual;
    DIFF
    MYSET()As you can see, it doesn't matter what order the elements of the set are specified in. As a SET, they are considered identical. The order of the elements when specifying the sets makes no difference.
    So, in your query, you can pass your elements to you IN operator in any order you like... but those elements are a SET of data... they have no order, except in the way you read them. Oracle see's no order to them, and cannot consider there to be an order to them.
    Therefore, if you need an order to the elements, using a SET of data is not the right approach as it doesn't contain an order. You would need to specify a set of data that contains information about the order, and you'd usually do that by inserting the elements into a table (Global Temporary Table perhaps?) with some additional column containing details of the order, and then in your query, you would use the ORDER BY clause to order on that additional ordering information.
    The only way to guarantee the order of output from an SQL statement is to specify an ORDER BY clause. ^1^
    ^1 There are a few exceptions such as hierarchical queries or data generating queries such as those with recursive subquery factoring or model clauses if used in certain ways^

  • Find all child tables - validate sql

    I have a table (tabA), In tabA i have a column (id) which is part of primary key
    Question: I need to know all the tables which have foreign keys refererring to tabA.id
    I used the following sql, please let me know if this is correct:
    select table_name
      from dba_constraints
    where (r_constraint_name) in ( select constraint_name
                                      from dba_constraints
                                     where table_name = 'tabA'
                                       and constraint_type in ( 'P', 'U' ) );

    On 11.2 you could try recursive subquery factoring:
    select *
    from ( with the_constraints( table_name
                               , constraint_name
                               , r_constraint_name
                               , lvl
           as ( select a.table_name
                ,      a.constraint_name
                ,      a.r_constraint_name
                ,      1 lvl
                from   all_constraints a
                where  a.table_name  = 'tabA'
                and    a.constraint_type = 'P'
                union all
                select c.table_name
                ,      nvl(( select constraint_name
                             from   all_constraints
                             where  table_name = c.table_name
                             and    constraint_type = 'P'
                          , c.constraint_name
                ,      c.r_constraint_name
                ,      lvl+1
                from   the_constraints p,
                       all_constraints c
                where  p.constraint_name = c.r_constraint_name
                and    c.constraint_type = 'R'
           search depth first by table_name set seq
           cycle table_name set is_cycle to 1 default 0
           select rownum rn
           ,      lpad('>', (lvl-1)*2, '-')||table_name relation
           ,      c.*
           from   the_constraints c
    order by rn desc;

  • Solving Sudoku in SQL?

    Hi. I'm wondering if one could solve a Sudoku puzzle with a SQL query given the initial configuration of the Sudoku is stored in a database table. Suppose I have a database table named InitSudoku storing the initial configuration of a 5x5 Sudoku. Each row in the table indicates which number (1 to 25) is initially placed in which square of the puzzle. For example, the row (15,3,9) means the number 15 is initially placed in the square at the 3rd row and the 9th column of the puzzle. What I would like to get is a result set that would give me a completion of the Sudoku. Does anyone think that is doable strictly within SQL with one or more queries (without using a procedural language like C or Java, which would require coding up an algorithm of solving Sudoku)?
    Thanks.

    The same guru has improved on this solution in 11gr2:
    [http://technology.amis.nl/blog/6404/oracle-rdbms-11gr2-solving-a-sudoku-using-recursive-subquery-factoring|http://technology.amis.nl/blog/6404/oracle-rdbms-11gr2-solving-a-sudoku-using-recursive-subquery-factoring]
    [http://tonyhasler.wordpress.com]

  • ORA-32031: illegal reference of a query name in WITH clause

    Oracle tutorial : http://www.oracle.com/technology/pub/articles/hartley-recursive.html#4
    When Executing this Query 6: Using a Recursive WITH Clause
    WITH C (CNO, PCNO, CNAME) AS
    (SELECT CNO, PCNO, CNAME -- initialization subquery
    FROM COURSEX
    WHERE CNO = 'C22' -- seed
    UNION ALL
    SELECT X.CNO, X.PCNO, X.CNAME -- recursive subquery
    FROM C, COURSEX X
    WHERE C.PCNO = X.CNO)
    SELECT CNO, PCNO, CNAME
    FROM C;
    Error: ORA-32031: illegal reference of a query name in WITH clause
    kindly suggest what need to do in case of recursion using subquery

    SCOTT@orcl> ed
    Wrote file afiedt.buf
      1  with c as
      2  (
      3  select empno,ename from emp
      4  where deptno=20
      5  union all
      6  select c.empno,c.ename from emp c
      7  where c.deptno=30
      8  )
      9* select * from c
    SCOTT@orcl> /
         EMPNO ENAME
          7566 xx
          7788 xx
          7876 xx
          7902 xx
          7499 xx
          7521 xx
          7654 xx
          7698 xx
          7844 xx
          7900 xx
    10 rows selected.
    SCOTT@orcl> ed
    Wrote file afiedt.buf
      1  with emp as
      2  (
      3  select empno,ename from emp
      4  where deptno=20
      5  union all
      6  select c.empno,c.ename from emp c
      7  where c.deptno=30
      8  )
      9* select * from emp
    SCOTT@orcl> /
    select empno,ename from emp
    ERROR at line 3:
    ORA-32031: illegal reference of a query name in WITH clause
    SCOTT@orcl>You can not use the same table name alongwith WITH clause's cursor name. See as above if i says with C as... its works; but if i says with emp as... it returned ora-32031, because it is the name of table.
    HTH
    Girish Sharma

  • Anlaytical Func

    hi
    select 1 slno, 1000 Amount , 0.12 Int_Rate, 1000*0.12 IntAmt from dual
    union
    select 2 slno, 1000 Amount , 0.13 Int_Rate ,1120 * 0.13 from dual
    SLNO     AMOUNT     INT_RATE     INTAMT
    1     1000     0.12     120
    2     1000     0.13     145.6
    Column 120 is the product of amount*int_rate(1000*0.12)
    Column 145.6 is the product of amount*int_rate(1000*0.12)*int_rate(1000*0.13)
    Can i get the help from somebody to compute using an analytical function to get the result
    Thanks in Advance

    user639304 wrote:
    Hi,
    That's great Sven W. In SQL, we have something to sum the values of rows, but we have nothing for the product of values of rows (or, at least, if something exist to express directly the product of numbers, we don't often use it) . So I was thinking to how use the existing functionalities of SQL in order to have the product of values in a given column, and I was thinking to the ln and exp functions. But I didn't arrive to the point where Sven W. has arrived. Sven W. has used the formula:
    x1 * x2 * ... * xn = exp(ln(x1) + ln (x2) + ... + ln(xn)), in other terms, roughly speaking,
    Product of values = exp(Sum of the ln of these values).Thanks for the explaination. I didn't had a proper idea how to write one myself. ;)
    A minor issue with this solution is that it might be a little CPU intensive. For example I had to add rounding, because the floating point math involved led to rounding issues.
    So if we need this often, it could be better to build our own aggregate_multiplication function. This is less complicated then one often thinks.
    Oh and here is the solution using a recursive with clause. I build it upon nicosas version, but changed the math to be consistent with my previous examples.
    Op wasn't very clear about the math behind and I think that led to much confusion.
    with t as (
         select 1 slno, 1000 Amount , 0.12 Int_Rate from dual
         union all
         select 2 slno, 0 Amount , 0.13 Int_Rate from dual
         union all
         select 3 slno, 0 Amount , 0.14 Int_Rate from dual
      order by slno -- this is important
    ------ end of sample data ------
    ------ This removes the gap-problem, by introducing a sequential row number
    , t2 as (select rownum rn, slno, Amount, Int_Rate
             from t)
    ------ trec below is a recursive with clause (AKA recursive subquery factoring) ------
    trec(rn, slno,amount,int_rate) as
         select rn,slno,amount*(1+int_rate),int_rate
      from t2 base
      where rn=1
         union all
         select t3.rn,t3.slno,trec.amount*(1+t3.int_rate),t3.int_rate
         from t2 t3
         join trec     on t3.rn=trec.rn+1
    ------ just query the recursive with clause ------
    select * from trec
    RN SLNO AMOUNT INT_RATE
    1    1   1120     0,12
    2    2 1265,6     0,13
    3    3 1442,784     0,14 This is the important line
    trec.amount*(1+t3.int_rate)
    Essentially this puts the amount from the previous row up for multiplication with interest from the current row. And sets it a the new amount.
    Edited by: Sven W. on Aug 17, 2012 3:07 PM - added with clause solution
    Edited by: Sven W. on Aug 17, 2012 3:10 PM - Typo correction

Maybe you are looking for