oracle递归查询

/*--建表语句
CREATE TABLE SC_DISTRICT
(
  ID         NUMBER(10)                  NOT NULL,
  PARENT_ID  NUMBER(10),
  NAME       VARCHAR2(255 BYTE)          NOT NULL
);

ALTER TABLE SC_DISTRICT ADD (
  CONSTRAINT SC_DISTRICT_PK
 PRIMARY KEY
 (ID));

ALTER TABLE SC_DISTRICT ADD (
  CONSTRAINT SC_DISTRICT_R01 
 FOREIGN KEY (PARENT_ID) 
 REFERENCES SC_DISTRICT (ID));*/
 
-- 插入数据:
--INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(0,null,'中国');
/*INSERT INTO SC_DISTRICT(ID,NAME) VALUES(1,'广东省');

INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(2,1,'广州市');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(3,1,'深圳市'); 

INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(4,2,'越秀区');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(5,2,'天河区');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(6,2,'黄浦区');

INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(7,3,'福田区');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(8,3,'南山区');

INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(9,8,'南山');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(10,8,'南头');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(11,8,'蛇口街道');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(12,8,'沙河街道');
 
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(13,6,'外滩街道');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(14,6,'南京东路街道');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(15,6,'老西门街道');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(16,6,'半淞园路街道');*/

-- Oracle中的select语句可以用start with...connect by prior子句实现递归查询,connect by 是结构化查询中用到的

--查询某节点的所有子孙节点
--查询广州市下面的所有行政组织(结果包含当前节点):
SELECT * FROM SC_DISTRICT  START WITH NAME='广州市'
CONNECT BY PRIOR ID=PARENT_ID
--查询指定节点的递归根节点
--查询老西门街道所属的市:
--CONNECT_BY_ROOT 操作的功能就是获取根节点记录的字段信息。这个功能在 9i当中可以利用 SYS_CONNECT_BY_PATH来实现
--虽然9i中的实现比10g要麻烦一些,但是利用SYS_CONNECT_BY_PATH还是可以实现这个功能的。

SELECT  ID, PARENT_ID, NAME,
    SUBSTR( SYS_CONNECT_BY_PATH(ID, '/') || '/',  2, 
 INSTR(SYS_CONNECT_BY_PATH(ID, '/') || '/', '/', 1, 2) - 2)
  /* CONNECT_BY_ROOT(ID) */  CITY_ID,
    SUBSTR( SYS_CONNECT_BY_PATH(NAME, '/') || '/',  2, 
 INSTR(SYS_CONNECT_BY_PATH(NAME, '/') || '/', '/', 1, 2) - 2)
       /*CONNECT_BY_ROOT(NAME)*/ CITY_NAME  FROM   SC_DISTRICT  WHERE  NAME='老西门街道'
       START WITH PARENT_ID=1 CONNECT BY PRIOR ID=PARENT_ID
       
--在10g中 Oracle提供了新的操作: CONNNECT_BY_ROOT,通过这个操作,可以获取树形查询根记录的字段
SELECT  ID, PARENT_ID, NAME,CONNECT_BY_ROOT(ID)  CITY_ID,
CONNECT_BY_ROOT(NAME) CITY_NAME  FROM   SC_DISTRICT  WHERE  NAME='老西门街道'
 START WITH PARENT_ID=1 CONNECT BY PRIOR ID=PARENT_ID
 
--CONNECT BY子句伪列的应用 LEVEL:查询节点层次,从1开始。
--CONNECT_BY_ISLEAF:查询节点是否是叶子节点,是则为1,不是则为0
--在10g中Oracle提供了新的伪列:CONNECT_BY_ISLEAF,通过这个伪列,可以判断当前的记录是否是树的叶节点
SELECT   ID,   NAME,   PARENT_ID,   LEVEL,   CONNECT_BY_ISLEAF
FROM     SC_DISTRICT START WITH NAME='广州市'
  CONNECT BY PRIOR ID=PARENT_ID  ORDER BY ID;
--CONNECT_BY_ISLEAF可以判断当前记录是否是树的叶节点。而这个功能在9i中没有简单的方法来实现,只能通过分析函数来进行判断:
--利用分析函数可以相对简单的在9i实现CONNECT_BY_ISLEAF伪列的功能
SELECT   ID,   NAME,   PARENT_ID,  -- LEVEL,   CONNECT_BY_ISLEAF
case when lead(levels)over(order by rn)>levels then 0 else 1 end leaf
FROM (select rownum rn,id,PARENT_ID,NAME,level levels from SC_DISTRICT 
START WITH NAME='广州市' CONNECT BY PRIOR ID=PARENT_ID ORDER BY ID);

--查询递归路径  查询广州市下行政组织递归路径
SELECT  ID, NAME, PARENT_ID, SUBSTR(SYS_CONNECT_BY_PATH(NAME,'->'),3) NAME_PATH
FROM  SC_DISTRICT START   WITH NAME='广州市' CONNECT BY PRIOR ID=PARENT_ID

 

posted @ 2013-08-13 23:04  蜜雪粮液  阅读(604)  评论(0编辑  收藏  举报