SQL ORACLE - 带有重复行的BOM爆炸 - 以...开头...由先前连接...由

时间:2018-02-01 23:26:56

标签: sql oracle hierarchical-data connect-by

您是否可以支持我确定如何删除由于BOM结构本身重复的Child项而导致的语句start with ... connected by prior...order sibling by完成的BOM爆炸中的重复?

起始表"BOM_table"是一个带有列的无序列表:

  • BOM_LEVEL
  • CHILD
  • PARENT

我知道第一级的CHILD(本次讨论改名为CHILD_LVL1)

在std情况下,我使用SQL语句

获得了良好的结果
select *
from BOM_table
start with CHILD = CHLD_LVL1
Connect by prior CHILD = PARENT
Order sibling by CHILD 

结果是基于LVL关系的具有正确CHILD顺序的表

BUT 我有相同的情况,其中CHILD项目存在于具有相同PARENT的不同BOM点中。

例如我在BOM#2 PARENT中有相同的代码,WITH#1 CHILD每个都有相同的代码。提到的SQL语句的结果是,对于这些父母中的每一个,我都将#2 CHILD与总共#4 CHILD相关联

1 个答案:

答案 0 :(得分:0)

爆炸的最常见原因是形成错误的START WITH / CONNECT BY子句。这是我在其上写的文章的摘录。它假设我们从SCOTT.EMP中的标准14行开始。

过滤与导航

如何导航层次结构的定义与SQL中WHERE子句谓词附带的过滤完全不同。为了证明这一点,EMP表中的14行已被复制为多个地理区域的一组行,如清单7所示。表中现在有42行,标准的14行为EAST复制两次,北部和南部地区。

Listing 7

SQL> alter table emp add region varchar2(10);

Table altered.

SQL> update emp set region = 'NORTH';

14 rows updated.

SQL>
SQL> insert into emp
  2  select
  3    empno, ename, job, mgr, hiredate, sal, comm, deptno,
  4    decode(r,1,'SOUTH',2,'EAST') region
  5  from emp,
  6       ( select rownum r from dual connect by level <= 2 )
  7  where region = 'NORTH';

28 rows created.

SQL>
SQL> select region, count(*)
  2  from   emp
  3  group by region;

REGION       COUNT(*)
---------- ----------
NORTH              14
SOUTH              14
EAST               14

让我们假设只需要为NORTH区域获取14行的层次结构。使用清单2中所示的相同查询似乎是直观的,但使用额外的谓词将REGION限制为NORTH。清单8显示了结果。

Listing 8
SQL> select empno, rpad(' ',level*3)||ename ename, mgr
  2  from   emp
  3  where  region = 'NORTH'
  4  connect by prior empno = mgr
  5  start  with mgr is null;

     EMPNO ENAME                                           MGR
---------- ---------------------------------------- ----------
      7839    KING
      7566       JONES                                    7839
      7788          SCOTT                                 7566
      7876             ADAMS                              7788
      ...
      ...
      7782       CLARK                                    7839
      7934          MILLER                                7782
      7934          MILLER                                7782
      7934          MILLER                                7782

136 rows selected.

请注意,返回的输出不是14行而是136行,即使应用了将结果限制为仅限于NORTH区域的谓词。

要了解此问题的原因,请考虑正在处理的第一个NORTH区域行。 START WITH子句是MANAGER IS NULL,因此将分配三个King行,每个区域对应一个,然后CONNECT BY操作将开始。 CONNECT BY子句是PRIOR EMPNO = MANAGER,因此对于每个KING记录,将连接三个相关的雇员,每个区域一个,这将迅速增加查询遍历整个层次结构时返回的行数。只有在建立层次关系时才应用WHERE子句谓词,因此即使结果集只包含REGION = NORTH的行,也会执行大量冗余工作与其他区域的错误连接,因为CONNECT BY语法和START WITH语法没有

•将自己限制为仅从NORTH区域开始,

•无法确保在连接到层次结构中的下一个条目时

该行从同一区域映射到后续行的区域。

清单9显示了此查询的更正语法。它始于管理者,这些管理者是空的,但也只在北部地区。然后,它确保在从一个经理连接到后续员工时,连接的定义还包括一个公共区域。这与处理ANSI连接语法的方式是同义的,即,层次连接条件与随后将作为过滤器应用的WHERE子句谓词之间存在明显差异。

这引起了对层次结构查询的共同正确批评,即它们运行速度太慢或消耗了太多资源。通常原因是CONNECT BY信息不完整,导致处理的行数远远多于需要的行。

Listing 9
SQL> select empno, rpad(' ',level*3)||ename ename, mgr
  2  from   emp
  3  connect by prior empno = mgr
  4         and  region = 'NORTH'
  5  start  with mgr is null
  6         and  region = 'NORTH';

     EMPNO ENAME                                           MGR
---------- ---------------------------------------- ----------
      7839    KING
      7566       JONES                                    7839
      7788          SCOTT                                 7566
      7876             ADAMS                              7788
      7902          FORD                                  7566
      7369             SMITH                              7902
      7698       BLAKE                                    7839
      7499          ALLEN                                 7698
      7521          WARD                                  7698
      7654          MARTIN                                7698
      7844          TURNER                                7698
      7900          JAMES                                 7698
      7782       CLARK                                    7839
      7934          MILLER                                7782

14 rows selected.

你可能会问&#34;那么在分层查询中使用WHERE子句是什么?&#34; WHERE子句的存在仍然有效,不是为了定义层次结构,而是为了定义数据的过滤。例如,一旦实例化了NORTH区域层次结构,该要求可能只针对那些包含在某个SALARY之上的员工。