`
zgqynx
  • 浏览: 1355871 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

START WITH and CONNECT BY in Oracle SQL

阅读更多
START WITH and CONNECT BY in Oracle SQL
摘自http://www.adp-gmbh.ch/ora/sql/connect_by.html
http://www.adp-gmbh.ch/
  select ... start with initial-condition connect by nocycle recurse-condition

select ... connect by recurse-condition

select ... start with initial-condition connect by nocycle recurse-condition

select ... connect by recurse-condition
The start with .. connect by clause can be used to select data that has a hierarchical relationship (usually some sort of parent->child (boss->employee or thing->parts).
It is also being used when an sql execution plan is explained. recurse-condition can make use of the keyword prior:
connect by
  prior foo = bar
This construct establishes the recursion. All records that are part of the next lower hierarchical level are found by having bar = foo. foo is a value found in the current hierarchical level.
A simple example
In the following example, the table from which that data is selected consists of just these attributes: parent and child. We make sure (by means of a unique constraint) that the child is uniqe within the table. This is just like in the real life where (as of yet) a child cannot have two different mothers. The data filled into the table is such that a the sum over the children with the same parent is the value of the parent:
set feedback off

create table test_connect_by (
  parent     number,
  child      number,
  constraint uq_tcb unique (child)
);
5 = 2+3
insert into test_connect_by values ( 5, 2);
insert into test_connect_by values ( 5, 3);
18 = 11+7
insert into test_connect_by values (18,11);
insert into test_connect_by values (18, 7);
17 = 9+8
insert into test_connect_by values (17, 9);
insert into test_connect_by values (17,;
26 = 13+1+12
insert into test_connect_by values (26,13);
insert into test_connect_by values (26, 1);
insert into test_connect_by values (26,12);
15=10+5
insert into test_connect_by values (15,10);
insert into test_connect_by values (15, 5);
38=15+17+6
insert into test_connect_by values (38,15);
insert into test_connect_by values (38,17);
insert into test_connect_by values (38, 6);
38, 26 and 18 have no parents (the parent is null)
insert into test_connect_by values (null, 38);
insert into test_connect_by values (null, 26);
insert into test_connect_by values (null, 18);
Now, let's select the data hierarchically:
select lpad(' ',2*(level-1)) || to_char(child) s
  from test_connect_by
  start with parent is null
  connect by prior child = parent;
This select statement results in:
38
  15
    10
    5
      2
      3
  17
    9
    8
  6
26
  13
  1
  12
18
  11
  7
Interpreting connect by statements
How must a start with ... connect by select statement be read and interpreted? If Oracle encounters such an SQL statement, it proceeds as described in the following pseude code.
for rec in (select * from some_table) loop
  if FULLFILLS_START_WITH_CONDITION(rec) then
    RECURSE(rec, rec.child);
  end if;
end loop;

procedure RECURSE (rec in MATCHES_SELECT_STMT, new_parent IN field_type) is
  begin
  APPEND_RESULT_LIST(rec);    
  for rec_recurse in (select * from some_table) loop
    if FULLFILLS_CONNECT_BY_CONDITION(rec_recurse.child, new_parent) then
      RECURSE(rec_recurse,rec_recurse.child);
    end if;
  end loop;
end procedure RECURSE;
Thanks to Frank Trenkamp who spotted an error in the logic in the above pseudo code and corrected it.
Pruning branches
Sometimes, it might be a requirement to only partially retrieve a hierarchical tree and to prune branches. Here, a tree is filled. Each child is the number of its parent plus a new digit on the right side.
create table prune_test (
  parent  number,
  child   number
);

insert into prune_test values (null,   1);
insert into prune_test values (null,   6);
insert into prune_test values (null,   7);

insert into prune_test values (   1,  12);
insert into prune_test values (   1,  14);
insert into prune_test values (   1,  15);

insert into prune_test values (   6,  61);
insert into prune_test values (   6,  63);
insert into prune_test values (   6,  65);
insert into prune_test values (   6,  69);

insert into prune_test values (   7,  71);
insert into prune_test values (   7,  74);

insert into prune_test values (  12, 120);
insert into prune_test values (  12, 124);
insert into prune_test values (  12, 127);

insert into prune_test values (  65, 653);

insert into prune_test values (  71, 712);
insert into prune_test values (  71, 713);
insert into prune_test values (  71, 715);

insert into prune_test values (  74, 744);
insert into prune_test values (  74, 746);
insert into prune_test values (  74, 748);

insert into prune_test values ( 712,7122);
insert into prune_test values ( 712,7125);
insert into prune_test values ( 712,7127);

insert into prune_test values ( 748,7481);
insert into prune_test values ( 748,7483);
insert into prune_test values ( 748,7487);
Now, we want to retrieve the tree, but prune everything below the branch 1 and 71. It would be false to put these into a where clause of the sql statement, rather, it belongs to the connect by clause:
select
  lpad(' ', 2*level) || child
from
  prune_test
start with
  parent is null
connect by
  prior child=parent
  and parent not in (1, 71);
  
This returns:
  1
  6
    61
    63
    65
      653
    69
  7
    71
    74
      744
      746
      748
        7481
        7483
        7487
See also another example for pruning.
Do two items stand in a ancestor descendant relationship
Sometimes, one want's to know if two items are in an ancestor descendant relationship, that is if XYZ as grandfather, or grand-grandfather, or ... of ABC. The following template of a query can be used to determine that.
set feedback off

drop table parent_child;

create table parent_child(parent_ varchar2(20), child_ varchar2(20));

insert into parent_child values (null,  'a')

insert into parent_child values (  'a',  'af');
insert into parent_child values (  'a',  'ab');
insert into parent_child values (  'a',  'ax');

insert into parent_child values ( 'ab', 'abc');
insert into parent_child values ( 'ab', 'abd');
insert into parent_child values ( 'ab', 'abe');

insert into parent_child values ('abe','abes');
insert into parent_child values ('abe','abet');

insert into parent_child values ( null,   'b');

insert into parent_child values (  'b',  'bg');
insert into parent_child values (  'b',  'bh');
insert into parent_child values (  'b',  'bi');

insert into parent_child values ( 'bi', 'biq');
insert into parent_child values ( 'bi', 'biv');
insert into parent_child values ( 'bi', 'biw');
The following query 'asks' for a parent and a supposed child (grand child, grand grand child) and answers the question if the are indeed in an ancester successor relationship.
set verify off

select
  case when count(*) > 0 then
    '&&parent is an ancestor of &&child' else
    '&&parent is no ancestor of &&child' end
    "And here's the answer"
from
  parent_child
where
  child_ = '&&child'
start with
  parent_ = '&&parent'
connect by
  prior child_ = parent_;

undefine child
undefine parent
Features of 9i
sys_connect_by_path
With sys_connect_by_path it is possible to show the entire path from the top level down to the 'actual' child:
Using hierarchical result sets
With this technique, it is possible to show all kind of hierarchical data relations. Here is an example that lists privileges, roles and users in their hierarchical relation. See also flat hiearchy.
connect_by_root
connect_by_root is a new operator that comes with Oracle 10g and enhances the ability to perform hierarchical queries. I have yet to dig into this subject and will write about it when things become clearer.
connect_by_is_leaf
connect_by_isleaf is a new operator that comes with Oracle 10g and enhances the ability to perform hierarchical queries. I have yet to dig into this subject and will write about it when things become clearer.
connect_by_iscycle
connect_by_is_cycle is a new operator that comes with Oracle 10g and enhances the ability to perform hierarchical queries. I have yet to dig into this subject and will write about it when things become clearer.
Thanks
Thanks to Peter Bruhn, Jonathan Schmalze, Jeff Jones, Keith Britch and Fabian Iturralde who each pointed out an error, misstake or typo on this page.
Further links
On storing hierarchical data 
分享到:
评论

相关推荐

    Oracle start with.connect by prior子句实现递归查询

    ### Oracle Start With.Connect By Prior 子句实现递归查询 #### 概述 在Oracle数据库中,`Start With.Connect By Prior`子句是执行递归查询的一种强大工具,主要用于处理层次结构数据。这类数据通常存在于组织...

    oracle数据库startwith用法

    ### Oracle数据库中的START WITH 和 CONNECT BY 用法详解 在Oracle数据库中,处理层次结构数据时,`START WITH` 和 `CONNECT BY` 是非常有用的两个关键字。这些关键字可以帮助我们在查询时构建出树形或者层级结构的...

    Oracle_start_with_connect_by_prior_用法

    ### Oracle中的START WITH CONNECT BY PRIOR 用法详解 #### 一、概念介绍 在Oracle数据库中,`START WITH` 和 `CONNECT BY PRIOR` 是两个非常强大的特性,主要用于处理具有层级结构的数据。这两个特性可以帮助我们...

    树状数据库表:Oracle中start with...connect by prior子句用法

    `START WITH...CONNECT BY PRIOR`是Oracle SQL中的一个特性,用于处理具有层级关系的数据。这个子句允许我们遍历和查询具有父子关系的数据,例如部门和其下属子部门,或者员工和他们的上级经理。 1. **START WITH...

    ORACLE查询树型关系(connect_by_prior_start_with)

    Oracle 查询树型关系是指使用 START WITH 和 CONNECT BY 子句来实现 SQL 的层次查询。从 Oracle 9i 开始,可以通过 SYS_CONNECT_BY_PATH 函数实现将父节点到当前行内容以“path”或者层次元素列表的形式显示出来。 ...

    Oracle_start_with_connect_by_prior_用法[文].pdf

    Oracle 连接查询是指使用 START WITH 和 CONNECT BY 语句来实现递归查询的方法,这种方法可以生成树形结构的数据。在 Oracle 中,START WITH 语句用于指定递归查询的开始记录,而 CONNECT BY 语句用于指定递归查询的...

    connect by的使用探索

    [ WHERE condition ][ [ START WITH condition ] CONNECT BY condition [ ORDER SIBLINGS BY expression ] ] ``` 其中,`START WITH`子句用于指定查询的起始节点,`CONNECT BY`子句用于指定查询的递归条件。 ...

    oracle connect by level 应用

    通常,`CONNECT BY`与`START WITH`一起使用,`START WITH`指定了层级遍历的起始节点。 例如,假设我们有一个员工表(EMPLOYEE),其中包含上级员工ID(MANAGER_ID)字段,我们可以使用以下查询来展示员工的管理层次...

    Oracle的Connect By使用示例

    Oracle数据库通过提供`START WITH...CONNECT BY`语句来简化这类查询操作。此功能最早出现在Oracle 8.1.6版本,并一直沿用至今,成为处理递归查询的强大工具之一。 #### 二、Connect By与Start With详解 1. **...

    Oracle和SqlServer语法区别

    可以看到,Oracle的SELECT语句支持更多的子句,例如START WITH U CONNECT BY、INTERSECT和MINUS等。这些子句在SqlServer中不支持,但是可以使用其他方式实现相同的结果。 二、函数和过程 Oracle和SqlServer都支持...

    MySQL多种递归查询方法.docx

    在Oracle数据库中,递归查询可以通过`START WITH CONNECT BY PRIOR`语句实现。此语句允许用户按照树状结构来检索数据。 ##### 1. `START WITH CONNECT BY PRIOR`用法详解 **基本语法**: ```sql SELECT * FROM ...

    ORACLE和SQL Server的语法区别

    START WITH U CONNECT BY {...} ``` - **SQL Server:** SQL Server提供了类似的SELECT语句结构,但并不支持`START WITH ... CONNECT BY` 子句。为了实现层次结构查询,可以使用递归公共表表达式(Recursive CTEs...

    Oracle递归查询start with connect by prior的用法

    在Oracle中,`START WITH` 和 `CONNECT BY` 是进行递归查询的关键字,它们允许我们从一个特定的根节点出发,沿着预定义的关系链接遍历整个树形结构。本文将深入探讨这两个关键字的用法,并通过实例来说明其在实际...

    Beginning Oracle SQL

    - **层次查询**:使用`CONNECT BY`和`START WITH`子句进行层次结构查询。 ```sql SELECT employee_name, manager_name FROM employees START WITH manager_name IS NULL CONNECT BY PRIOR employee_name = ...

    Oracle递归树形结构查询功能

    递归树形结构查询主要依赖于`CONNECT BY`和`PRIOR`关键字,它们允许我们构建复杂的层级查询,以展示数据的层次关系。 在Oracle中,树形结构查询的基本语法如下: ```sql SELECT [LEVEL], * FROM table_name START ...

    浅谈Oracle下connect by原理.pdf

    CONNECT BY [NOCYCLE] condition [AND condition] [START WITH condition] START WITH condition CONNECT BY [NOCYCLE] condition [AND condition] ``` 其中,`START WITH`用于指定查询的起始节点,而`CONNECT BY`...

    Oracle和SQL_Server的语法区别

    - Oracle 的 `START WITH U CONNECT BY` 用于创建层次查询,SQL Server 可以通过递归公共表表达式(CTE)或存储过程实现类似功能。 - Oracle 支持 `INTERSECT` 和 `MINUS` 集合运算符,而 SQL Server 用 `EXISTS` 和...

    start connect by

    在SQL查询中,`START WITH` 和 `CONNECT BY` 是两个关键的子句,它们用于构建层次结构查询,通常在处理具有上下级关系的数据时非常有用,如员工与经理的关系、组织结构或者产品分类等。这两个子句是Oracle数据库特有...

Global site tag (gtag.js) - Google Analytics