Oracle递归详解

start with ...connect by prior 函数详解

  • 1、描述:
    • 什么是递归?
  • 2、语法:
  • 3、数据:
      • 建表语句:
      • 数据:
  • 4、案例:
      • 1、查询`1000`节点儿子节点
      • 2、查询`1200`节点所有子节点
      • 3、查找`1260`节点所有上级节点
      • 4、查询`1260`节点的簇兄弟(在同一层级)
      • 5、查询递归路径
      • 6、查询节点是否为叶节点(叶节点为1,非叶节点为0)

1、描述:

什么是递归?

古之欲明明德于天下者,先治其国;欲治其国者,先齐其家;欲齐其家者,先修其身;欲修其身者,先正其心;欲正其心者,先诚其意。

start with...connect by prior用于实现递归查询树形结构。如果不好理解proir的向上向下,就记住如果想往上遍历就把上级节点放在prior后,如果想往下遍历反之将下级节点放在prior后。简单粗暴。

2、语法:

 SELECT *
   FROM t_name
 {WHERE 条件一}
  START WITH 条件二
CONNECT BY {PRIOR PARENT=ID|PARENT=PRIOR ID} 

3、数据:

建表语句:

-- Create table
create table AREA_SHANDONG
(
  area_id     VARCHAR2(10),
  area_name   VARCHAR2(20),
  parent_id   VARCHAR2(10),
  parent_name VARCHAR2(20)
)
tablespace TS_TAB_ICRMAPP_DAT
  pctfree 10
  initrans 1
  maxtrans 255
  storage
  (
    initial 64K
    next 1M
    minextents 1
    maxextents unlimited
  );
-- Add comments to the table 
comment on table AREA_SHANDONG
  is '地区信息表-山东';
-- Add comments to the columns 
comment on column AREA_SHANDONG.area_id
  is '地区号';
comment on column AREA_SHANDONG.area_name
  is '地区名';
comment on column AREA_SHANDONG.parent_id
  is '上级地区号';
comment on column AREA_SHANDONG.parent_name
  is '上级地区名称';

数据:

prompt Importing table area_shandong...
set feedback off
set define off
insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1000', '山东省', null, null);

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1100', '济南市', '1000', '山东省');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1200', '青岛市', '1000', '山东省');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1210', '市南区', '1200', '青岛市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1220', '市北区', '1200', '青岛市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1230', '崂山区', '1200', '青岛市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1240', '李村区', '1200', '青岛市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1250', '城阳区', '1200', '青岛市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1260', '黄岛区', '1200', '青岛市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1300', '烟台市', '1000', '山东省');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1310', '莱山区', '1300', '烟台市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1320', '福山区', '1300', '烟台市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1330', '牟平区', '1300', '烟台市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1340', '开发区', '1300', '烟台市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1350', '高新区', '1300', '烟台市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1360', '长岛县', '1300', '烟台市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1370', '海阳市', '1300', '烟台市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1371', '东村街道', '1370', '海阳市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1372', '方园街道', '1370', '海阳市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1373', '凤城街道', '1370', '海阳市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1374', '龙山街道', '1370', '海阳市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1375', '行村镇', '1370', '海阳市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1376', '新安镇', '1370', '海阳市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1377', '小集镇', '1370', '海阳市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1378', '徐家店镇', '1370', '海阳市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1379', '李典镇', '1370', '海阳市');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1400', '淄博市', '1000', '山东省');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1500', '威海市', '1000', '山东省');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1600', '东营市', '1000', '山东省');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1700', '潍坊市', '1000', '山东省');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1800', '日照市', '1000', '山东省');

insert into area_shandong (AREA_ID, AREA_NAME, PARENT_ID, PARENT_NAME)
values ('1900', '德州市', '1000', '山东省');

prompt Done.

4、案例:

1、查询1000节点儿子节点

SQL> SELECT *
  2    FROM area_shandong
  3   WHERE parent_id = '1000' ;
AREA_ID    AREA_NAME            PARENT_ID  PARENT_NAME
---------- -------------------- ---------- --------------------
1100       济南市               1000       山东省
1200       青岛市               1000       山东省
1300       烟台市               1000       山东省
1400       淄博市               1000       山东省
1500       威海市               1000       山东省
1600       东营市               1000       山东省
1700       潍坊市               1000       山东省
1800       日照市               1000       山东省
1900       德州市               1000       山东省
9 rows selected

2、查询1200节点所有子节点

SQL>  SELECT *
  2     FROM area_shandong
  3    START WITH parent_id='1200'
  4  CONNECT BY PRIOR area_id = parent_id;
AREA_ID    AREA_NAME            PARENT_ID  PARENT_NAME
---------- -------------------- ---------- --------------------
1210       市南区               1200       青岛市
1220       市北区               1200       青岛市
1230       崂山区               1200       青岛市
1240       李村区               1200       青岛市
1250       城阳区               1200       青岛市
1260       黄岛区               1200       青岛市
6 rows selected

3、查找1260节点所有上级节点

SQL>  SELECT * from area_shandong start with area_id='1260' connect by prior parent_id=area_id;
AREA_ID    AREA_NAME            PARENT_ID  PARENT_NAME
---------- -------------------- ---------- --------------------
1260       黄岛区               1200       青岛市
1200       青岛市               1000       山东省
1000       山东省 

4、查询1260节点的簇兄弟(在同一层级)

SQL> with tmp as(
  2   select a.*, level leaf
  3   from area_shandong a
  4   start with a.parent_id is null
  5   connect by a.parent_id = prior a.area_id)
  6   select *
  7   from tmp
  8   where leaf = (select leaf from tmp where area_id =1260 );
AREA_ID    AREA_NAME            PARENT_ID  PARENT_NAME                LEAF
---------- -------------------- ---------- -------------------- ----------
1210       市南区               1200       青岛市                        3
1220       市北区               1200       青岛市                        3
1230       崂山区               1200       青岛市                        3
1240       李村区               1200       青岛市                        3
1250       城阳区               1200       青岛市                        3
1260       黄岛区               1200       青岛市                        3
1310       莱山区               1300       烟台市                        3
1320       福山区               1300       烟台市                        3
1330       牟平区               1300       烟台市                        3
1340       开发区               1300       烟台市                        3
1350       高新区               1300       烟台市                        3
1360       长岛县               1300       烟台市                        3
1370       海阳市               1300       烟台市                        3
13 rows selected

以下两个案例可以额外学习一下,另外还有一个函数个人不常用就不写了,有兴趣可以自己去查一下。

5、查询递归路径

SQL> select area_id, area_name, parent_id,
  2   substr(sys_connect_by_path(area_name,'->'),3) path
  3   from area_shandong
  4   start with area_id='1000'
  5   connect by prior area_id=parent_id;
AREA_ID    AREA_NAME            PARENT_ID  PATH
---------- -------------------- ---------- --------------------------------------------------------------------------------
1000       山东省                          山东省
1100       济南市               1000       山东省->济南市
1200       青岛市               1000       山东省->青岛市
1210       市南区               1200       山东省->青岛市->市南区
1220       市北区               1200       山东省->青岛市->市北区
1230       崂山区               1200       山东省->青岛市->崂山区
1240       李村区               1200       山东省->青岛市->李村区
1250       城阳区               1200       山东省->青岛市->城阳区
1260       黄岛区               1200       山东省->青岛市->黄岛区
1300       烟台市               1000       山东省->烟台市
1310       莱山区               1300       山东省->烟台市->莱山区
1320       福山区               1300       山东省->烟台市->福山区
1330       牟平区               1300       山东省->烟台市->牟平区
1340       开发区               1300       山东省->烟台市->开发区
1350       高新区               1300       山东省->烟台市->高新区
1360       长岛县               1300       山东省->烟台市->长岛县
1370       海阳市               1300       山东省->烟台市->海阳市
1371       东村街道             1370       山东省->烟台市->海阳市->东村街道
1372       方园街道             1370       山东省->烟台市->海阳市->方园街道
1373       凤城街道             1370       山东省->烟台市->海阳市->凤城街道
AREA_ID    AREA_NAME            PARENT_ID  PATH
---------- -------------------- ---------- --------------------------------------------------------------------------------
1374       龙山街道             1370       山东省->烟台市->海阳市->龙山街道
1375       行村镇               1370       山东省->烟台市->海阳市->行村镇
1376       新安镇               1370       山东省->烟台市->海阳市->新安镇
1377       小集镇               1370       山东省->烟台市->海阳市->小集镇
1378       徐家店镇             1370       山东省->烟台市->海阳市->徐家店镇
1379       李典镇               1370       山东省->烟台市->海阳市->李典镇
1400       淄博市               1000       山东省->淄博市
1500       威海市               1000       山东省->威海市
1600       东营市               1000       山东省->东营市
1700       潍坊市               1000       山东省->潍坊市
1800       日照市               1000       山东省->日照市
1900       德州市               1000       山东省->德州市
32 rows selected

6、查询节点是否为叶节点(叶节点为1,非叶节点为0)

SQL>  select m.*, connect_by_isleaf leaf
  2   from area_shandong m
  3   start with parent_id is null
  4   connect by parent_id = prior area_id;
AREA_ID    AREA_NAME            PARENT_ID  PARENT_NAME                LEAF
---------- -------------------- ---------- -------------------- ----------
1000       山东省                                                        0
1100       济南市               1000       山东省                        1
1200       青岛市               1000       山东省                        0
1210       市南区               1200       青岛市                        1
1220       市北区               1200       青岛市                        1
1230       崂山区               1200       青岛市                        1
1240       李村区               1200       青岛市                        1
1250       城阳区               1200       青岛市                        1
1260       黄岛区               1200       青岛市                        1
1300       烟台市               1000       山东省                        0
1310       莱山区               1300       烟台市                        1
1320       福山区               1300       烟台市                        1
1330       牟平区               1300       烟台市                        1
1340       开发区               1300       烟台市                        1
1350       高新区               1300       烟台市                        1
1360       长岛县               1300       烟台市                        1
1370       海阳市               1300       烟台市                        0
1371       东村街道             1370       海阳市                        1
1372       方园街道             1370       海阳市                        1
1373       凤城街道             1370       海阳市                        1
AREA_ID    AREA_NAME            PARENT_ID  PARENT_NAME                LEAF
---------- -------------------- ---------- -------------------- ----------
1374       龙山街道             1370       海阳市                        1
1375       行村镇               1370       海阳市                        1
1376       新安镇               1370       海阳市                        1
1377       小集镇               1370       海阳市                        1
1378       徐家店镇             1370       海阳市                        1
1379       李典镇               1370       海阳市                        1
1400       淄博市               1000       山东省                        1
1500       威海市               1000       山东省                        1
1600       东营市               1000       山东省                        1
1700       潍坊市               1000       山东省                        1
1800       日照市               1000       山东省                        1
1900       德州市               1000       山东省                        1
32 rows selected

你可能感兴趣的:(Oracle,oracle,sql,递归算法)