oracle递归查询 start with connect by prior

(1)创建表结构

-- Create table
createtable TB_DW_JBXX
(
  dwid    CHAR(10) notnull,
  dwmc    VARCHAR2(100) notnull,
  tcq     CHAR(2) notnull,
  dwlx    CHAR(2) notnull,
  dj      NUMBER(3) notnull,
  yxzt    CHAR(1) notnull,
  lsdwid  CHAR(10) notnull,
  dwid_dxt CHAR(10)
)
tablespace DATA
  pctfree10
  initrans1
  maxtrans255
  storage
  (
    initial64K
    minextents1
    maxextentsunlimited
  );
-- Add comments to thecolumns
commentoncolumn TB_DW_JBXX.dwid is'单位ID';
commentoncolumn TB_DW_JBXX.dwmc  is'单位名称';
commentoncolumn TB_DW_JBXX.tcq  is'所属统筹区';
commentoncolumn TB_DW_JBXX.dwlx  is'单位类型';
commentoncolumn TB_DW_JBXX.dj
  is'单位等级 0:路局;1:社保中心;2......n:基层单位';
commentoncolumn TB_DW_JBXX.yxzt is'有效状态 0:有效;1:无效';
commentoncolumn TB_DW_JBXX.lsdwid is'隶属的上层单位';
commentoncolumn TB_DW_JBXX.dwid_dxt is'单位ID_大系统';
-- Create/Recreateprimary, unique and foreign key constraints
altertable TB_DW_JBXX
  addconstraint PK_TB_DW_JBXX primarykey (DWID)
  usingindex
  tablespace INDX
  pctfree10
  initrans2
  maxtrans255
  storage
  (
    initial64K
    minextents1
    maxextentsunlimited
  );
-- Grant/Revoke objectprivileges
grantselecton TB_DW_JBXX toGUEST_XX;


(2)插入数据,略

树结构:

 

(3)语法说明

connect by 是结构化查询中用到的,其基本语法是:
select … from tablename

where 条件3

start with 条件1
connect by 条件2;

   

条件1 是根结点的限定语句,当然可以放宽限定条件,以取得多个根结点,实际就是多棵树。

条件2 是连接条件,其中用PRIOR表示上一条记录
条件3 是过滤条件,用于对返回的所有记录进行过滤

start with 子句:遍历起始条件,

START WITH 可以省略:不指定树的根,默认把Tree整个表中的数据从头到尾遍历一次,每一个数据做一次根,然后遍历树中其他节点信息.

connect by 子句:连接条件。STARTWITH 与CONNECT BY PRIOR位置可互换

关键词prior

  prior跟父节点列lsdwid放在一起,就是往父结点方向遍历;

  prior跟子结点列dwid放在一起,则往叶子结点方向遍历,

  lsdwid、dwid两列,谁放在“=”前都无所谓,关键是prior跟谁在一起。

  prior位置决定了检索是自底向上还是自顶向下

  "prior" 如果缺省:则只能查询到符合条件的起始行,并不进行递归查询。 

orderby 子句:排序,不用多说。

(4)测试

--0900000002(上海) /0900000001 (全局)

--用例(1)

SELECT * FROM tb_dw_jbxx d WHERE d.yxzt='0' START WITH d.dwid='0900000002'CONNECT BY PRIOR d.dwid=d.lsdwid;
SELECT * FROM tb_dw_jbxx d WHERE d.yxzt='0' START WITH d.dwid='0900000002'CONNECT BY d.lsdwid= PRIOR d.dwid;

以上sql语句查询结果是一样的。结果如下:


数据分析:

123条数据,(包含当前节点数据)自顶向下、向子节点方向遍历。

如果想获取当前节点的所有子节点(不包含当前节点),可以直接取lsdwid这列数据。或使用用例(2)语句。

"prior" 如果缺省:则只能查询到符合条件的起始行,并不进行递归查询。 

SELECT * FROM tb_dw_jbxx d WHERE d.yxzt='0' START WITH d.dwid='0900000002' CONNECT BY  d.dwid=d.lsdwid;

数据结果略。

--用例(2)

SELECT * FROMtb_dw_jbxx d WHERE d.yxzt='0' START WITH d.lsdwid='0900000002' CONNECT BY PRIORd.dwid=d.lsdwid;

结果数据如下所示:


数据分析:

122条数据,(不包含当前节点数据)自顶向下、向子节点方向遍历。

--用例(3)

SELECT * FROMtb_dw_jbxx d WHERE d.yxzt='0' START WITH d.dwid='0900000002' CONNECT BY  d.dwid= PRIOR d.lsdwid;

结果数据如下所示:


数据分析:

2条数据,(包含当前节点数据)自底向上、向子节点方向遍历。

如果想获取当前节点的所有父节点(不包含当前节点),可以直接取lsdwid这列数据。

--用例(4)

SELECT * FROMtb_dw_jbxx d WHERE /*d.yxzt='0' AND*/ d.lsdwid='0900000002' ;
SELECT * FROMtb_dw_jbxx d WHERE d.yxzt='0' START WITH d.lsdwid='0900000002' CONNECT BYd.dwid=  PRIOR d.lsdwid;

数据结果如下所示:


数据分析:

266条数据,(包含当前节点数据)自底向上、向子节点方向遍历。

如果想获取当前节点的所有父节点(不包含当前节点),可以直接取lsdwid这列数据。

'0900000002'下的一级子单位94条(SELECT * FROMtb_dw_jbxx d WHERE /*d.yxzt='0' AND*/ d.lsdwid='0900000002'),其中有效的78条,无效的16条。

266条数据中,94条全局的数据,94条上海的数据,78条子节点数据。

本来以为会,78条全局的数据,78条上海的数据,78条子节点数据。

而实际数据却是,94,94,78;

查询原因:是16条无效的数据,也递归查询父节点。

所以:where 语句,可以看成与递归查询无关。只是对整个结果起过滤作用。

猜你喜欢

转载自blog.csdn.net/tane_1018/article/details/78834363