古之欲明明德于天下者,先治其国;欲治其国者,先齐其家;欲齐其家者,先修其身;欲修其身者,先正其心;欲正其心者,先诚其意。
start with...connect by prior
用于实现递归查询树形结构。如果不好理解proir
的向上向下,就记住如果想往上遍历就把上级节点放在prior
后,如果想往下遍历反之将下级节点放在prior
后。简单粗暴。
SELECT *
FROM t_name
{WHERE 条件一}
START WITH 条件二
CONNECT BY {PRIOR PARENT=ID|PARENT=PRIOR ID}
-- 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.
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
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
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 山东省
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
以下两个案例可以额外学习一下,另外还有一个函数个人不常用就不写了,有兴趣可以自己去查一下。
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
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