Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Confusão com Oracle CONNECT BY


Como um CONNECT BY consulta é executada e avaliada - passo a passo (por exemplo).

Digamos que temos a seguinte tabela e uma conexão por consulta:
select * from mytable;

         X
----------
         1 
         2 
         3 
         4 

SELECT level, m.* 
FROM mytable m
START with x = 1
CONNECT BY PRIOR x +1 = x  OR  PRIOR x + 2 = x 
ORDER BY level;

Etapa 1:

Selecione as linhas da tabela mytable que atendem a um START WITH condição, atribua LEVEL =1 ao conjunto de resultados retornado:
 CREATE TABLE step1 AS
 SELECT 1 "LEVEL", X from mytable
 WHERE x = 1;

 SELECT * FROM step1;

         LEVEL          X
    ---------- ----------
             1          1

Etapa 2

Aumente o nível em 1:
LEVEL = LEVEL + 1

Junte-se ao conjunto de resultados retornado na etapa anterior com mytable usando CONNECT BY condições como as condições de junção.

Nesta cláusula PRIOR column-name refere-se ao conjunto de resultados retornado pela etapa anterior e column-name simples refere-se à mytable tabela:
CREATE TABLE step2 AS
SELECT 2 "LEVEL", mytable.X from mytable
JOIN step1 "PRIOR"
ON "PRIOR".x +1 = mytable.x or  "PRIOR".x + 2 = mytable.x;

select * from step2;

     LEVEL          X
---------- ----------
         2          2 
         2          3

ETAPA x+1

Repita #2 até que a última operação retorne um conjunto de resultados vazio.

Etapa 3
CREATE TABLE step3 AS
SELECT 3 "LEVEL", mytable.X from mytable
JOIN step2 "PRIOR"
ON "PRIOR".x +1 = mytable.x or  "PRIOR".x + 2 = mytable.x;

select * from step3;

     LEVEL          X
---------- ----------
         3          3 
         3          4 
         3          4

Etapa 4
CREATE TABLE step4 AS
SELECT 4 "LEVEL", mytable.X from mytable
JOIN step3 "PRIOR"
ON "PRIOR".x +1 = mytable.x or  "PRIOR".x + 2 = mytable.x;

select * from step4;

     LEVEL          X
---------- ----------
         4          4 

Etapa 5
CREATE TABLE step5 AS
SELECT 5 "LEVEL", mytable.X from mytable
JOIN step4 "PRIOR"
ON "PRIOR".x +1 = mytable.x or  "PRIOR".x + 2 = mytable.x;

select * from step5;

no rows selected

A etapa 5 não retornou nenhuma linha, então agora finalizamos a consulta

Última etapa

UNION ALL resultados de todas as etapas e devolvê-lo como resultado final:
SELECT * FROM step1
UNION ALL
SELECT * FROM step2
UNION ALL
SELECT * FROM step3
UNION ALL
SELECT * FROM step4
UNION ALL

SELECT * FROM step5;

     LEVEL          X
---------- ----------
         1          1 
         2          2 
         2          3 
         3          3 
         3          4 
         3          4 
         4          4 

Agora vamos aplicar o procedimento acima à sua consulta:
SELECT * FROM dual;

DUMMY
-----
X 

SELECT LEVEL FROM DUAL CONNECT BY rownum>5;

Etapa 1

Como a consulta não contém o START WITH cláusula, o Oracle seleciona todos os registros da tabela de origem:
CREATE TABLE step1 AS
SELECT 1 "LEVEL" FROM dual;

select * from step1;

     LEVEL
----------
         1 

Etapa 2
CREATE TABLE step2 AS
SELECT 2 "LEVEL" from dual
JOIN step1 "PRIOR"
ON rownum > 5

select * from step2;

no rows selected

Como a última etapa não retornou nenhuma linha, vamos finalizar nossa consulta.

Última etapa
SELECT * FROM step1
UNION ALL

SELECT * FROM step2;

     LEVEL
----------
         1

A análise da última consulta:
select level from dual connect by rownum<10;

Deixo para você como tarefa de casa.