`

BOM物料表从connect_by_isleaf说起

 
阅读更多

下面这样写是错的。写出这样的语句的实质就是自己误导自己。


with test_cc as (
  select 'A' root,'B' parent_root from dual union
  select 'B','C' from dual union
  select 'C','D' from dual union
  select 'C','E' from dual union
  select 'E','F' from dual
)
select level lv,
       connect_by_root(root) conn_root,
       connect_by_root(parent_root) conn_parent_root,
       --最后一个是A的才是leaf
       connect_by_isleaf,
       sys_connect_by_path(parent_root,'>')||'>'||root path
from test_cc
connect by prior root=parent_root;






下面这样写才是对的。


with test_cc as (
  select 'A' root,'B' parent_root from dual union
  select 'B','C' from dual union
  select 'C','D' from dual union
  select 'C','E' from dual union
  select 'E','F' from dual
)
select level lv,
       connect_by_isleaf,
       connect_by_root(root)||sys_connect_by_path(parent_root,'>') path
from test_cc
connect by prior parent_root=root;







这边有一个规则:

1.connect by prior 后面跟的是什么,sys_connect_by_path(的后面就要跟着同样的一个东西。否则路径会错。

2.并且不可以使用:root||sys_connect_by_path(parent_root,'>')来连。
必须用 connect_by_root(root)||sys_connect_by_path(parent_root,'>')  才能得到正确的结果。

3.这里还有个规则务必一定要记住:
root  parent_root
  B       C
  A       B
  B       D
如果我们想 A,B 去跟上一行的 B,C 或下一行的 B,D 连接
正确的写法是:connect by prior parent_root= root;【1】
而不是写成:  connect by parent_root= prior root;【2】
虽然他们表达的意思是一样的。但是对connect_by_isleaf有着相当大的影响。因为你【2】的写法实际上是你把整棵树倒过来了。

A.如果我们写成 connect by parent_root= prior root;会发现sys_connect_by_path的路径是对的。但是connect_by_isleafe的内容就是错的。它把整棵树倒过来了。根节点变成了叶子节点。【站在自己那里连对方】

B.如果我们写成 connect by prior parent_root = root;会发现sys_connect_by_path 的路径是错的而且还少了很多分支。但是connect_by_isleafe的内容是对的。【站在对方那里连自己】
















有一个BOM结构表,如下:






首先我要得到顶级零件到最下级零件的全路径:
select level lv,
       connect_by_isleaf lf, 
       part_no,component_part,per_assembly,
       connect_by_root(part_no) rt_part_no,
       connect_by_root(component_part) rt_component_part,
       sys_connect_by_path(per_assembly,'>') path_value,
       connect_by_root(part_no)||sys_connect_by_path(component_part,'>') path_correct,
       substr(sys_connect_by_path(per_assembly,'*'),2,100) path_exp_value
from CY_BOM_COMPONENT --(select * from CY_BOM_COMPONENT where part_no='ABDEF')
connect by nocycle prior component_part = part_no 
order by path_correct;










然后我在这些数据的基础上group by.我只要那些叶子节点的内容求和即可得到单个最下级零件和所有零件的总数,因为我把每个叶子节点的地方放置了一个从根到叶子路径的所有值。

select * from(
    select level lv,
           connect_by_isleaf lf, 
           part_no,component_part,per_assembly,
           connect_by_root(part_no) rt_part_no,
           connect_by_root(component_part) rt_component_part,
           sys_connect_by_path(per_assembly,'>') path_value,
           connect_by_root(part_no)||sys_connect_by_path(component_part,'>') path_correct,
           substr(sys_connect_by_path(per_assembly,'*'),2,100) path_exp_value
    from CY_BOM_COMPONENT --(select * from CY_BOM_COMPONENT where part_no='ABDEF')
    connect by nocycle prior component_part = part_no 
)where lf=1
order by path_correct;

最后算总的结果是:

create or replace
function f_calcExpValue(expr varchar2) return number is r number;
begin
	execute immediate 'select '||expr||' from dual' into r;
	return r;
end f_calcExpValue;


select --wm_concat(lv) lv,
       --max(lf) lf,
       rt_part_no,
       --wm_concat(path_correct) path_correct_group,
       --wm_concat(path_exp_value) path_exp_group,
       --replace(wm_concat(path_exp_value),',','+') path_exp_value
       f_calcExpValue(replace(wm_concat(path_exp_value),',','+')) path_exp_value
--select *
from(
    select level lv,
           connect_by_isleaf lf, 
           part_no,component_part,per_assembly,
           connect_by_root(part_no) rt_part_no,
           connect_by_root(component_part) rt_component_part,
           sys_connect_by_path(per_assembly,'>') path_value,
           connect_by_root(part_no)||sys_connect_by_path(component_part,'>') path_correct,
           substr(sys_connect_by_path(per_assembly,'*'),2,100) path_exp_value
    from CY_BOM_COMPONENT --(select * from CY_BOM_COMPONENT where part_no='ABDEF')
    connect by nocycle prior component_part = part_no 
)where lf=1
group by rt_part_no
order by rt_part_no;







create or replace
function f_calcExpValue(expr varchar2) return number is r number;
begin
	execute immediate 'select '||expr||' from dual' into r;
	return r;
end f_calcExpValue;


select wm_concat(lv) lv,
       max(lf) lf,
       rt_part_no,
       wm_concat(path_correct) path_correct_group,
       --wm_concat(path_exp_value) path_exp_group,
       --replace(wm_concat(path_exp_value),',','+') path_exp_value
       f_calcExpValue(replace(wm_concat(path_exp_value),',','+')) path_exp_value,
       wm_concat(path_exp_value_single) path_exp_value_single_group
--select *
from(
    select lv,lf,rt_part_no,path_correct,path_exp_value,
           component_part||':'||f_calcExpValue(path_exp_value) path_exp_value_single
    from(
        select level lv,
               connect_by_isleaf lf, 
               part_no,component_part,per_assembly,
               connect_by_root(part_no) rt_part_no,
               connect_by_root(component_part) rt_component_part,
               sys_connect_by_path(per_assembly,'>') path_value,
               connect_by_root(part_no)||sys_connect_by_path(component_part,'>') path_correct,
               substr(sys_connect_by_path(per_assembly,'*'),2,100) path_exp_value
        from CY_BOM_COMPONENT --(select * from CY_BOM_COMPONENT where part_no='ABDEF')
        connect by nocycle prior component_part = part_no 
    )where lf=1
)
group by rt_part_no
order by rt_part_no;









select rt_part_no as 顶级零件,
       wm_concat(path_exp_value_single) 需各最下级零件的个数,
       f_calcExpValue(replace(wm_concat(path_exp_value),',','+')) as 需最下级零件总个数
from(
    select lv,lf,rt_part_no,path_correct,path_exp_value,
           component_part||':'||f_calcExpValue(path_exp_value) path_exp_value_single
    from(
        select level lv,
               connect_by_isleaf lf, 
               part_no,component_part,per_assembly,
               connect_by_root(part_no) rt_part_no,
               connect_by_root(component_part) rt_component_part,
               sys_connect_by_path(per_assembly,'>') path_value,
               connect_by_root(part_no)||sys_connect_by_path(component_part,'>') path_correct,
               substr(sys_connect_by_path(per_assembly,'*'),2,100) path_exp_value
        from CY_BOM_COMPONENT --(select * from CY_BOM_COMPONENT where part_no='ABDEF')
        connect by nocycle prior component_part = part_no 
    )where lf=1
)group by rt_part_no
order by rt_part_no;




  • 大小: 27.1 KB
  • 大小: 38.1 KB
  • 大小: 35.9 KB
  • 大小: 123.9 KB
  • 大小: 69.6 KB
  • 大小: 64.4 KB
  • 大小: 71.5 KB
  • 大小: 30.4 KB
分享到:
评论

相关推荐

    MySQL实现类似于connect_by_isleaf的功能MySQL方法或存储过程

    在MySQL中,面对类似Oracle的`connect_by_isleaf`功能的需求,即查找并修改指定ID的所有子级记录,可以通过自连接、存储过程或者递归函数等方法实现。这里我们主要探讨两种MySQL的实现方式:一种是使用用户定义的...

    ORACLE查询树型关系(connect_by_prior_start_with)

    使用 START WITH 和 CONNECT BY 子句可以实现 SQL 的层次查询,并且可以使用 SYS_CONNECT_BY_PATH 函数和 CONNECT_BY_ROOT、CONNECT_BY_ISLEAF、CONNECT_BY_ISCYCLE 等伪列函数来增强层次查询的能力。

    oracle-sql

    总的来说,Oracle SQL提供了丰富的层次查询和数据清理工具,如SYS_CONNECT_BY_PATH、CONNECT_BY_ISLEAF、CONNECT_BY_ROOT和CONNECT_BY_ISCYCLE等,使得在处理层次结构数据和大量数据清理时更为便捷高效。同时,理解...

    学习SQL常用方法

    查询命令:select CONNECT_BY_ISLEAF, dirindex, fatherindex, RPAD(' ',2*(LEVEL-1)) || dirname from t_tonedirlib start with fatherindex = 0 connect by fatherindex = prior dirindex; 这些知识点总结了 SQL ...

    【Oracle】树状结构查询

    SELECT LEVEL, CONNECT_BY_ISCYCLE, CONNECT_BY_ISLEAF, SYS_CONNECT_BY_PATH(a.ename, '/'), a.* FROM empa WHERE a.empno <> 7369 START WITH a.empno = 7839 CONNECT BY NOCYCLE PRIOR a.empno = a.mgr; ``` ...

    Oracle常用操作(项目中积累的经验)

    这些关键词用于构建树状结构,其中`LEVEL`表示层次,`CONNECT_BY_ISLEAF`标识叶子节点,`SYS_CONNECT_BY_PATH`生成路径,`START WITH`指定起始节点,`CONNECT BY PRIOR`定义层级关系,`CONNECT_BY_ROOT`查找根节点,...

    Oracle的Connect By使用示例

    例如,在一个员工表中,如果想要查找所有下属及其下属的下属,可以使用`CONNECT BY PRIOR employee_id = manager_id`这样的表达式来定义上下级关系。 2. **Start With**:用来定义查询的起点,即指定哪一行作为树形...

    Oracle 数据库特殊查询总结

    1. 查询本节点及本节点以下的所有节点: ...SELECT RPAD( ' ', 2*(LEVEL-1), '-' ) || DEPNAME "DEPNAME",CONNECT_BY_ROOT DEPNAME "ROOT",CONNECT_BY_ISLEAF "ISLEAF",LEVEL ,SYS_CONNECT_BY_PATH(DEPNAM

    浅谈Oracle下connect by原理.pdf

    Connect By是Oracle用来进行层次查询的语法结构,其原理可以被理解为深度优先遍历(DFS),即从根节点开始,先遍历左子树,再遍历右子树,以此类推,直到找到所有的叶子节点。当使用Connect By进行查询时,每一行...

    oracle高级语句

    - **`CONNECT_BY_ISLEAF`**: 如果当前行是叶子节点则返回1,否则返回0。 - **`SYS_CONNECT_BY_PATH`**: 返回路径字符串,其中包含从根到当前节点的所有节点的值。 **示例代码:** ```sql SELECT empno, mgr, ename,...

    Oracle树查询总结

    `CONNECT_BY_ISLEAF` 表达式返回一个布尔值,表示当前节点是否为叶子节点,即没有子节点。 在处理树查询时,应避免 `NULL` 的 `parent_id` 值,因为这可能导致全表扫描,影响性能。建议使用特定的值(如 0)来表示...

    Oracle SQL实用讲解,最基本最实用的相关讲解

    - `CONNECT_BY_ISLEAF`标记叶子节点,值为1表示是叶子节点,0则不是。 3. **rpad函数**: `rpad`函数在Oracle SQL中用于右填充字符串,确保字符串达到指定的长度。例如,在给定的例子中,它将乘积的结果填充到...

    Oracle内建函数大全

    - CONNECT_BY_ROOT/CONNECT_BY_ISLEAF:在层次查询中使用,标识根节点或叶子节点。 10. **系统信息函数** - USER:返回当前用户的名称。 - DBMS_METADATA:获取对象的DDL语句,用于脚本生成。 以上只是Oracle内...

    sql的left join和count应用

    `LEFT JOIN` 是一种联接(JOIN)类型,它返回所有左表(在本例中是 `TPL` 表)的记录,即使在右表(同样也是 `TPL` 表)中没有匹配的记录。如果在右表中没有找到匹配,结果将用 `NULL` 填充右边列的值。 接着,`...

    实际工作中常用sql积累及总结

    例如,通过CONNECT_BY_ROOT和CONNECT_BY_ISLEAF等函数在Oracle数据库中实现递归查询。 6. **数据库备份与还原**:定期备份数据库是防止数据丢失的关键步骤。SQL提供多种备份类型,如完整备份、差异备份和日志备份。...

    ORACLE 合辑

    **CONNECT_BY_ISLEAF:** - 判断当前节点是否为叶子节点。 **CONNECT_BY_ISCYCLE:** - 检测是否存在环路。 **SYS_CONNECT_BY_PATH:** - 生成路径字符串,如:`SELECT SYS_CONNECT_BY_PATH(id, '/') FROM table`....

    oracle函数

    11. **递归函数**:如LEVEL和CONNECT_BY_ISLEAF用于层次查询,实现数据的递归遍历。 12. **排序函数**:RANK(), DENSE_RANK(), ROW_NUMBER()在查询结果中提供行号。 13. **窗口函数**:如LEAD(), LAG(), RANK()等...

    oracle常用函数

    - 示例:`SELECT CONNECT_BY_ROOT id, connect_by_isleaf FROM table START WITH condition CONNECT BY PRIOR id = parent_id;` 以上列举了部分Oracle数据库中常用的函数,它们在日常的数据库管理和数据分析中发挥...

    权限管理数据库设计文档

    - ISLEAF:标记模块是否为叶子节点(是否有子模块)。 - NODEURLTITLE:超链接的title属性,提供额外的描述信息。 5. 系统模块登录表(TB_ADM_MODULE_LOGIN) - UserId:与用户信息表关联,表示用户可以访问的...

Global site tag (gtag.js) - Google Analytics