zoukankan      html  css  js  c++  java
  • oracle中的树状查询

    oracle中的树状查询

    工作中经常会遇到将数据库中的数据以树的形式展现的需求。以下我们来看一下该需求在Oracle中如何实现。

    首先我们需要有一个树形的表结构(当然有时候会出现表结构不是典型的树形结构,而是多表存储,需要根据多表连接查询生成树)

    一、树型表结构:
    节点ID  上级ID  节点名称


    二、用法: 
    select 节点ID,节点名称,level
    from 表名
    connect by prior 节点ID=上级节点ID
    start with 上级节点ID=节点值

    说明:
    1、常见的树形结构为公司组织机构、地区……
    2、求节点ID以上的结构,或以下的结构,将“节点ID=上级节点ID”左右顺序换一下即可。
    3、Level为Oracle的特殊字段,表示“层”的意思。当前节点ID的下一层节点为“1”。


    测试SQL: 1,建立表结构

     CREATE TABLE "TEAMB0"."MATBOM" 

    ( "FACT_NO" CHAR(4) NOT NULL ENABLE,
    "CARRY_MK" CHAR(1) NOT NULL ENABLE,
    "MAIN_MAT_NO" CHAR(20) NOT NULL ENABLE,
    "SUB_MAT_NO" CHAR(20) NOT NULL ENABLE,
    "PRD_CODE" CHAR(1) NOT NULL ENABLE,
    "PRD_RATE" NUMBER(8,5) NOT NULL ENABLE,
    "MODIFY_USER" VARCHAR2(60),
    "MODIFY_DATE" CHAR(14),
    "BLOC_MK" CHAR(1)
    ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
    STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
    PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
    TABLESPACE "USER_DATA"

     插入数据:

    Insert into MATBOM (FACT_NO,CARRY_MK,MAIN_MAT_NO,SUB_MAT_NO,PRD_CODE,PRD_RATE,MODIFY_USER,MODIFY_DATE,BLOC_MK) values ('216M','N','A020408G02A059 ','A020408G01A059 ','3',1,null,null,null);
    Insert into MATBOM (FACT_NO,CARRY_MK,MAIN_MAT_NO,SUB_MAT_NO,PRD_CODE,PRD_RATE,MODIFY_USER,MODIFY_DATE,BLOC_MK) values ('216M','N','A020408G15A059 ','A020408G01A059 ','3',1,null,null,null);
    Insert into MATBOM (FACT_NO,CARRY_MK,MAIN_MAT_NO,SUB_MAT_NO,PRD_CODE,PRD_RATE,MODIFY_USER,MODIFY_DATE,BLOC_MK) values ('216M','N','A020408G18A059 ','A020408G01A059 ','5',1,'S6042382','20081020133712',null);
    Insert into MATBOM (FACT_NO,CARRY_MK,MAIN_MAT_NO,SUB_MAT_NO,PRD_CODE,PRD_RATE,MODIFY_USER,MODIFY_DATE,BLOC_MK) values ('216M','N','N090823G09A059 ','A020408G01A059 ','1',1,'S6042382','20081208150154',null);
    Insert into MATBOM (FACT_NO,CARRY_MK,MAIN_MAT_NO,SUB_MAT_NO,PRD_CODE,PRD_RATE,MODIFY_USER,MODIFY_DATE,BLOC_MK) values ('216M','N','A020408G01A059 ','A020408G01A059-1 ','3',1,null,null,null);
    INSERT INTO MATBOM (FACT_NO,CARRY_MK,MAIN_MAT_NO,SUB_MAT_NO,PRD_CODE,PRD_RATE,MODIFY_USER,MODIFY_DATE,BLOC_MK) VALUES ('216M','N','A020408G01A059 ','A020408G01A059-2 ','3',1,NULL,NULL,NULL);

    INSERT INTO MATBOM (FACT_NO,CARRY_MK,MAIN_MAT_NO,SUB_MAT_NO,PRD_CODE,PRD_RATE,MODIFY_USER,MODIFY_DATE,BLOC_MK)
    VALUES ('216M','N','T1-A020408G02A059 ','A020408G02A059 ','3',1,NULL,NULL,NULL);

    SQL查询

    --prior放的左右位置决定了检索是自底向上还是自顶向下. 左边是自上而下(找子节点),右边是自下而上(找父节点)
    --找父节点

    SELECT MAIN_MAT_NO,sub_mat_no,level
    FROM MATBOM
    CONNECT BY SUB_MAT_NO = PRIOR MAIN_MAT_NO
    START WITH SUB_MAT_NO = 'A020408G01A059 ';

    ;or

    SELECT MAIN_MAT_NO,sub_mat_no,level
    FROM MATBOM

    START WITH SUB_MAT_NO = 'A020408G01A059 '
    CONNECT BY SUB_MAT_NO = PRIOR MAIN_MAT_NO;

    ;

    --找子节点节点
    -- (子节点)SUB_MAT_NO 为A020408G01A059 的子材料,以及A020408G01A059 子材料下的所有直接或间接子材料(prior 在左边, prior、MAIN_MAT_NO(等号右边)在右边)

    SELECT MAIN_MAT_NO,sub_mat_no,level
    FROM MATBOM
    START WITH SUB_MAT_NO = 'A020408G01A059'
    CONNECT BY PRIOR SUB_MAT_NO = MAIN_MAT_NO;

    三、性能问题  

      对于 start with connect by语句的执行,oracle会进行递归查询,当数据量大的时候会产生性能相关问题。

    --生成执行计划
    EXPLAIN PLAN FOR SELECT * FROM MATBOM START WITH SUB_MAT_NO = 'A020408G01A059' CONNECT BY SUB_MAT_NO = PRIOR MAIN_MAT_NO;

    -- 查询执行计划
    select * from table( dbms_xplan.display);

    语句执行计划结果如下:

    Plan hash value: 1868394721

    --------------------------------------------------------------------------------------------------
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    --------------------------------------------------------------------------------------------------
    | 0 | SELECT STATEMENT | | 7 | 840 | 3 (0)| 00:00:01 |
    |* 1 | CONNECT BY NO FILTERING WITH START-WITH| | | | | |
    | 2 | TABLE ACCESS FULL | MATBOM | 7 | 840 | 3 (0)| 00:00:01 |
    --------------------------------------------------------------------------------------------------

    Predicate Information (identified by operation id):
    ---------------------------------------------------

    1 - access("SUB_MAT_NO"=PRIOR "MAIN_MAT_NO")
    filter("SUB_MAT_NO"='A020408G01A059')

    Note
    -----
    - dynamic sampling used for this statement

    通过该执行计划得知,改语句执行了7步操作,才将结果集查询并返回。当需要查询条件进行过滤的时候,我们可以通过查看执行计划从而对sql进行优化。



  • 相关阅读:
    1380. Lucky Numbers in a Matrix
    672. Bulb Switcher II
    1375. Bulb Switcher III
    1376. Time Needed to Inform All Employees
    1372. Longest ZigZag Path in a Binary Tree
    PHP中curl_multi并发详解【转】
    php中$_REQUEST、$_POST、$_GET的区别【转】
    Post请求的两种编码格式:application/x-www-form-urlencoded和multipart/form-data【转】
    PHP $_FILES函数详解【转】
    php接收二进制流【转】
  • 原文地址:https://www.cnblogs.com/scwbky/p/9746738.html
Copyright © 2011-2022 走看看