programing

테이블의 CONNECT BY LEVEL이 추가 행을 반환하는 이유는 무엇입니까?

starjava 2023. 7. 21. 20:27
반응형

테이블의 CONNECT BY LEVEL이 추가 행을 반환하는 이유는 무엇입니까?

수준별 연결을 사용하면 테이블에서 수행할 때 너무 많은 행이 반환되는 것 같습니다.무슨 일이 일어나고 있는지에 대한 논리는 무엇입니까?

다음 표를 가정합니다.

create table a ( id number );

insert into a values (1);
insert into a values (2);
insert into a values (3);

이 쿼리는 12개 행(SQL Fiddle)을 반환합니다.

 select id, level as lvl
   from a
connect by level <= 2
  order by id, level

열 LVL 값이 1인 표 A의 각 행, 열 LVL이 2인 표 A의 각 행, 즉:

ID | LVL---+-----1 |  11 |  21 |  21 |  22 |  12 |  22 |  22 |  23 |  13 |  23 |  23 |  2

이 쿼리는 동일한 결과를 반환하는 이 쿼리와 동일합니다.

 select id, level as lvl
   from dual
  cross join a
connect by level <= 2
  order by id, level

왜 이 쿼리들이 12개의 행을 반환하는지 또는 ID 열의 각 값에 대해 LVL이 2인 행이 3개이고 LVL이 1인 행만 있는 이유를 이해할 수 없습니다.

"연결"된 레벨 수를 3으로 늘리면 ID. 1의 각 값에 대해 13개 행이 반환됩니다. 여기서 LVL은 1, 3이고 LVL은 2이고 9는 3입니다.이는 반환된 행이 표 A에서 LVL - 1의 거듭제곱에 해당하는 행의 수임을 의미하는 것으로 보입니다.

저는 이 쿼리들이 6개의 행을 반환하는 다음과 같을 것이라고 생각했습니다.

select id, lvl
  from ( select level  as lvl
           from dual
        connect by level  <= 2
                )
 cross join a
 order by id, lvl

문서는 저에게 무슨 일이 일어나야 하는지 설명하는 데 있어 특별히 명확하지 않습니다.이러한 능력에 무슨 일이 일어나고 있으며 왜 처음 두 쿼리는 세 번째 쿼리와 같지 않습니까?

connect by는 되지않다니습 없이 됩니다.start with과 과prior연산자, 하위 행을 상위 행에 결합하는 데 제한이 없습니다.이러한 상황에서 Oracle은 모든 행을 상위 레벨의 모든 행에 연결하여 가능한 모든 계층 순열을 반환합니다.

SQL> select b
  2       , level as lvl
  3       , sys_connect_by_path(b, '->') as ph
  4     from a
  5  connect by level <= 2
  6  ;

         B        LVL PH
       ---------- ---------- 
         1          1 ->1
         1          2 ->1->1
         2          2 ->1->2
         3          2 ->1->3
         2          1 ->2
         1          2 ->2->1
         2          2 ->2->2
         3          2 ->2->3
         3          1 ->3
         1          2 ->3->1
         2          2 ->3->2
         3          2 ->3->3

12 rows selected

첫 번째 쿼리에서는 수준별로 연결합니다.따라서 레벨이 <= 1이면 각 레코드를 한 번씩 얻게 됩니다.수준이 <= 2이면 각 수준이 1회(수준 1의 경우) + N회(여기서 N은 표의 레코드 수)가 됩니다.결과를 제한할 다른 조건이 없는 상태에서 레벨에 도달할 때까지 모든 레코드를 테이블에서 선택하기 때문에 교차 결합하는 것과 같습니다.레벨 <= 3의 경우 이 작업은 각 결과에 대해 다시 수행됩니다.

3개의 레코드에 대해:

  • Lvl 1: 3개의 기록(모두 레벨 1)
  • Lvl 2: 레벨 1이 있는 3개의 레코드 + 레벨 2가 있는 3*3 레코드 = 12
  • Lvl 3: 3 + 3*3 + 3*3 = 39(각각 13개의 레코드).
  • Lvl 4: 패턴이 보이기 시작하나요? :)

교차 결합이 아닙니다.교차 조인은 이 쿼리 결과에 레벨 2가 있는 레코드만 반환하는 반면, 이 연결 기준으로 레벨 1이 있는 레코드와 레벨 2가 있는 레코드를 가져오므로 3*3 레코드가 아닌 3+3*3이 됩니다.

최종 쿼리를 다른 쿼리와 비교할 때 사과와 오렌지를 비교하는 것입니다. 레벨이 1행 이중 테이블과 격리되어 있기 때문입니다.

이 쿼리를 고려해 보겠습니다.

 select id, level as lvl
   from a
connect by level <= 2
  order by id, level

즉, 테이블 세트부터 시작합니다(* From a 선택).그런 다음 반환된 각 행에 대해 이 행을 이전 행에 연결합니다.연결 기준으로 조인을 정의하지 않았으므로, 이것은 사실상 데카르트 조인입니다. 따라서 (1,2,3) 1의 3개 행이 2,1->3,2->1,2->3,3->1,3->2에 조인하고 그들도 스스로 조인할 때 이 조인은 레벨=2입니다. 그래서 우리는 9개의 조인을 가지고 있습니다.따라서 12개의 행(원래 "레벨 1" 행 3개 + 데카르트 집합)이 생성됩니다.

따라서 출력되는 행 수 = 행 수 + (행 수 ^2)

마지막 쿼리에서 레벨을 이 수준으로 분리합니다.

select level  as lvl
           from dual
        connect by level  <= 2

당연히 두 줄을 반환합니다.그러면 원래의 3개 행으로 데카르트되어 6개 행이 출력됩니다.

아래 기술을 사용하여 이 문제를 해결할 수 있습니다.

select id, level as lvl
   from a
      left outer join (select level l from dual connect by level <= 2) lev on 1 = 1
order by id

언급URL : https://stackoverflow.com/questions/13540661/why-does-connect-by-level-on-a-table-return-extra-rows

반응형