您的位置:首页 > 其它

connect by rownum及connect by level的内部执行原理及过程

2014-06-13 20:30 507 查看
来自兔子大神blog地址:http://www.itpub.net/thread-1570306-1-1.html

对于有N条记录的来说,如果没有递归条件,直接connect by level,先深度搜索,再广度,则

每个节点作为根节点,然后自身和其他节点为子节点,然后下个子节点还包括自身和其他节点,然后同样迭代

所以,总共记录数有N*2^0+N*2^1+.........    其中0,1....为level

则记F(N,l)为 select id,level from t connect by level<l 的结果集数目

那么,

F(N,1)=N

F(N,l) = F(N,l-1)*N+N

于是可以总结出

F(N,l)=∑power(N,p), p取值为[1,l)

总记录数N,level层数P

结果集数:T=∑N^x(x=1...p)

比如,总记录数为3,层数为3

则结果集数:3^1 +3^2 + 3^3 = 3+9+27=39
SELECT rowid,a,b,level,rownum FROM test1 CONNECT BY level<=3;

对于记录数N,则第m层记录数为N^m

N=3,LEVEL<=1    s=N

       LEVEL<=2    s=N^1+N^2

       LEVEL<=3    s=N^1+N^2+N^3

       ...

       LEVEL<=m s=N^1+N^2+N^3+....N^m

       等比数列q=N,a1=N

       s=N(1-N^m)/(1-N)  其中m为需要迭代的level最大值

dingjun123@ORADB> select * from t;

        ID

----------

         1

         1

已选择2行。

已用时间:  00: 00: 00.04

dingjun123@ORADB> select rownum from t connect by rownum <= 2;

    ROWNUM

----------

         1

         2

         3

已选择3行。

已用时间:  00: 00: 00.01

connect by 的本质分析

执行下面两句:

select level,rownum from dual connect by level<=10;

select level,rownum from dual connect by rownum<=10; 

两句显示的效果完全一样,

但是,如果select有2条或更多,效果就大不一样

select A.TABLE_NAME,level,rownum from (select * from USER_TABLES A WHERE ROWNUM<=2 ) A connect by level<=10;  --有2046条

select A.TABLE_NAME, level,rownum from (select * from USER_TABLES WHERE ROWNUM<=2) A connect by rownum<=10 ; --有11条;

所以,想咨询专家 connect by level 和 connect by rownum 的本质区别;

列个关系列表,也许可以通过数学归纳法,得出其中规律

select 的记录数(m)      connect by 层数(n)       by level 的记录数    by rownum的记录数

      1                          10                                 10                             10

      2                          10                                 2046                          11

      3                          10                                 88572                        12

      4                          10                               1398100                      13

by rownum的记录数 规律很明显:   connect by 层数(n)  +select 的记录数(m)    -1;

by level 的记录数 的规律还没找出

--深刻理解connect by的原理,理解statr with,connect by,理解层次如何生成的

--理解connect by level和connect by rownum的区别,比如掌握level如何生成,rownum如何生成

--connect by level是先做递归,然后判断level是否满足条件,如果有多行,则每行为根,没有其他条件则

--子节点是自身的子,其他节点也是自身的子。。。循环,因此,connect by level<0也是有结果的,相当于没有写

--connect by level<0是先做递归,先做1次递归,发现level=1,不满足条件,之后结束,并不是丢弃行(和where不同),根总会递归

--但是如果有下属的,不满足条件的,则会丢弃,详细见后面的例子

--connect by rownum,没有其他条件,是直接递归迭代第一行(反复),然后判断rownum条件,不满足条件结束。正是因为

--递归如果没有start with则每行都是根,先第一轮递归,递归到rownum<n不满足后结束,然后其他根肯定不满足,只选出自身一行。

--则剩余其他几行都显示一次,因为第1行递归结束后,继续其他行,发现都不满足,结束。这个rownum不是select里的rownum

--connect by 1=1就不结束了

--没有start with,没有prior...的迭代,不管是level,还是rownum,每行都是根节点,自身或其它节点是子节点

--区别是connect by level会先深度搜索,也就是根---自身---其他节点

--connect by rownum则是不停迭代自身(第一行),然后判断rownum。。。。

---有3行

--它只对第一行做循环,到ROWNUM=4的时候停止。然后另外两条叠加上去,这是因为没有START WITH, 所以第一层所有行都会选中。

如果是先把第一层数据拿出来,再循环,那么结果就不是这样了。

CONNECT BY里面最好用LEVEL控制,ROWNUM的生成顺序不是我们能控制的。

dingjun123@ORADB> SELECT rowid,a,b,level,rownum FROM test1 CONNECT BY rownum<7;         --迭代第一行,到第rownum=6结束,其他2行直接显示,select rownum不一样

ROWID                       A          B      LEVEL     ROWNUM

------------------ ---------- ---------- ---------- ----------

AAAVu6AAEAAAsF2AAA          1          1          1          1         --第1到第6反复递归第一行

AAAVu6AAEAAAsF2AAA          1          1          2          2

AAAVu6AAEAAAsF2AAA          1          1          3          3

AAAVu6AAEAAAsF2AAA          1          1          4          4

AAAVu6AAEAAAsF2AAA          1          1          5          5

AAAVu6AAEAAAsF2AAA          1          1          6          6

AAAVu6AAEAAAsF2AAB          1                     1          7      --不满足条件,递归结束

AAAVu6AAEAAAsF2AAC          1          2          1          8      --同上

已选择8行。

已用时间:  00: 00: 00.01

dingjun123@ORADB> SELECT rowid,a,b,level,rownum FROM test1 CONNECT BY rownum<-1;    --不满足条件,相当于没有写

ROWID                       A          B      LEVEL     ROWNUM

------------------ ---------- ---------- ---------- ----------

AAAVu6AAEAAAsF2AAA          1          1          1          1

AAAVu6AAEAAAsF2AAB          1                     1          2

AAAVu6AAEAAAsF2AAC          1          2          1          3

已选择3行。

已用时间:  00: 00: 00.01

dingjun123@ORADB> SELECT rowid,a,b,level,rownum FROM test1 CONNECT BY rownum<0;   --同上

ROWID                       A          B      LEVEL     ROWNUM

------------------ ---------- ---------- ---------- ----------

AAAVu6AAEAAAsF2AAA          1          1          1          1

AAAVu6AAEAAAsF2AAB          1                     1          2

AAAVu6AAEAAAsF2AAC          1          2          1          3

已选择3行。

已用时间:  00: 00: 00.01

dingjun123@ORADB> SELECT rowid,a,b,level,rownum FROM test1 CONNECT BY 1=0; --同上

ROWID                       A          B      LEVEL     ROWNUM

------------------ ---------- ---------- ---------- ----------

AAAVu6AAEAAAsF2AAA          1          1          1          1

AAAVu6AAEAAAsF2AAB          1                     1          2

AAAVu6AAEAAAsF2AAC          1          2          1          3

已选择3行。

已用时间:  00: 00: 00.01

dingjun123@ORADB> SELECT rowid,a,b,level,rownum FROM test1 CONNECT BY level<0;  --同上

ROWID                       A          B      LEVEL     ROWNUM

------------------ ---------- ---------- ---------- ----------

AAAVu6AAEAAAsF2AAA          1          1          1          1

AAAVu6AAEAAAsF2AAB          1                     1          2

AAAVu6AAEAAAsF2AAC          1          2          1          3

已选择3行。

dingjun123@ORADB> SELECT rowid,a,b,level,rownum FROM test1 CONNECT BY level<3;  --每行为根迭代,自身和其他行是子节点

ROWID                       A          B      LEVEL     ROWNUM

------------------ ---------- ---------- ---------- ----------

AAAVu6AAEAAAsF2AAA          1          1          1          1                     --根,其他包括自身的3行是子

AAAVu6AAEAAAsF2AAA          1          1          2          2

AAAVu6AAEAAAsF2AAB          1                     2          3

AAAVu6AAEAAAsF2AAC          1          2          2          4

AAAVu6AAEAAAsF2AAB          1                     1          5

AAAVu6AAEAAAsF2AAA          1          1          2          6

AAAVu6AAEAAAsF2AAB          1                     2          7

AAAVu6AAEAAAsF2AAC          1          2          2          8

AAAVu6AAEAAAsF2AAC          1          2          1          9

AAAVu6AAEAAAsF2AAA          1          1          2         10

AAAVu6AAEAAAsF2AAB          1                     2         11

AAAVu6AAEAAAsF2AAC          1          2          2         12

已选择12行。

SELECT rowid,a,b,level,rownum FROM test1 CONNECT BY level<4;       --3条记录有39行

ROWID                       A        B        LEVEL        ROWNUM

AAAVu6AAEAAAsF0AAA        1        1        1        1                ----

AAAVu6AAEAAAsF0AAA        1        1        2        2

AAAVu6AAEAAAsF0AAA        1        1        3        3                 第一行到第5行是level=2,第1行自身level=1,level=2

AAAVu6AAEAAAsF0AAB        1                3        4                 对于level=3的又从自身开始,N条记录

AAAVu6AAEAAAsF0AAC        1        2        3        5               总数目等比数列和a1(1-q^n)/(1-q)=N(1-N^level)/(1-N)

                                                                         =3(1-3^3)(1-3)

AAAVu6AAEAAAsF0AAB        1                2        6                  ----

AAAVu6AAEAAAsF0AAA        1        1        3        7

AAAVu6AAEAAAsF0AAB        1                3        8

AAAVu6AAEAAAsF0AAC        1        2        3        9

AAAVu6AAEAAAsF0AAC        1        2        2        10

AAAVu6AAEAAAsF0AAA        1        1        3        11

AAAVu6AAEAAAsF0AAB        1                3        12

AAAVu6AAEAAAsF0AAC        1        2        3        13

AAAVu6AAEAAAsF0AAB        1                1        14

AAAVu6AAEAAAsF0AAA        1        1        2        15

AAAVu6AAEAAAsF0AAA        1        1        3        16

AAAVu6AAEAAAsF0AAB        1                3        17

AAAVu6AAEAAAsF0AAC        1        2        3        18

AAAVu6AAEAAAsF0AAB        1                2        19

AAAVu6AAEAAAsF0AAA        1        1        3        20

AAAVu6AAEAAAsF0AAB        1                3        21

AAAVu6AAEAAAsF0AAC        1        2        3        22

AAAVu6AAEAAAsF0AAC        1        2        2        23

AAAVu6AAEAAAsF0AAA        1        1        3        24

AAAVu6AAEAAAsF0AAB        1                3        25

AAAVu6AAEAAAsF0AAC        1        2        3        26

AAAVu6AAEAAAsF0AAC        1        2        1        27

AAAVu6AAEAAAsF0AAA        1        1        2        28

AAAVu6AAEAAAsF0AAA        1        1        3        29

AAAVu6AAEAAAsF0AAB        1                3        30

AAAVu6AAEAAAsF0AAC        1        2        3        31

AAAVu6AAEAAAsF0AAB        1                2        32

AAAVu6AAEAAAsF0AAA        1        1        3        33

AAAVu6AAEAAAsF0AAB        1                3        34

AAAVu6AAEAAAsF0AAC        1        2        3        35

AAAVu6AAEAAAsF0AAC        1        2        2        36

AAAVu6AAEAAAsF0AAA        1        1        3        37

AAAVu6AAEAAAsF0AAB        1                3        38

AAAVu6AAEAAAsF0AAC        1        2        3        39

----------------例子---------------

DROP TABLE tt;

CREATE TABLE tt(ID number,NAME VARCHAR2(10));

INSERT INTO tt VALUES(1,'aa');

INSERT INTO tt VALUES(2,'bb');

INSERT INTO tt VALUES(3,'cc');

COMMIT;

加个level就明白了,connect by level递归,无其他条件,就是每行都是根,然后自身和其他行是子孙,反复迭代

SQL> select ID,NAME,LEVEL from tt connect by level < 3;

        ID NAME       LEVEL

---------- ---------- ----------

         1 aa                 1                                     --根

         1 aa                 2

         2 bb                2

         3 cc                 2                                     --包括自身的3个子孙,满足level<3条件结束

         2 bb                1

         1 aa                 2

         2 bb                2

         3 cc                 2

         3 cc                 1

         1 aa                 2

         2 bb                2

         3 cc                 2

12 rows selected

也就是对于记录数为N的,如果level最大为m,那么相应的层次c上面的记录数是N^c,因此所有的记录数就是N+N^2+N^3+....N^m=N(1-N^m)/(1-m),

比如3条记录数的,当level<4的话,m=3,则总记录数为39条。找个规律就行了,也就是先深度搜索

同样,下面的也是每行为根,不同的是只搜索level<id

注意一点,根总会递归出来的(不会丢弃),但是下属子节点会判断不满足丢弃行,

比如第一行,虽然id=1,不满足level<id,但是也会出现,和下面的类似

select * from dual connect by level <0;返回一行结果

SQL> select ID,NAME,LEVEL from tt connect by LEVEL < ID;

        ID NAME       LEVEL

---------- ---------- ----------

         1 aa                 1

         3 cc                 2                                       --bb的id=2不满足条件

         2 bb                 1

         3 cc                 2

         3 cc                 1

         3 cc                 2

6 rows selected

--因为level<=1或level<0都会返回一条数据

select rnum from

(select level rnum

from dual

connect by level <= 2 - 1)

where 2 <> 1

/

竟然返回

     RNUM

---------

        1

with t as

(select 1 id from dual union all

select 2 from dual)

select id,level from t connect by level<=10

order by id,level;

select 2*(1-power(2,10))/-1 from dual;

q≠1时 Sn=a1(1-q^n)/(1-q)=(a1-anq)/(1-q) 

q=1时Sn=na1

select * from all_objects connect by  rownum<=10;

在某个啥啥帖子里看到  rownum,也就是 COUNT 这个操作是最后生成的,在where之后

SELECT ROWNUM n2 FROM DUAL where level=4 CONNECT BY ROWNUM<=5

意味着.

先  递归第一次,然后level=1 ,此时该level不满足level=4的条件,因此 rownum是0,依然满足rownum<=5.

然后递归第二次,然后level=2,此时该level不满足level=4的条件,因此 rownum是0,依然满足rownum<=5.

然后递归第三次,然后level=3,此时该level不满足level=4的条件,因此 rownum是0,依然满足rownum<=5.

然后递归第四次,然后level=4,此时该level满足level=4的条件,因此 rownum是1,依然满足rownum<=5.

然后递归第五次,然后level=5,此时该level不满足level=4的条件,因此 rownum是1,依然满足rownum<=5.

.....

然后就是天荒地老..海枯石烂..精尽人亡...内存溢出..

大概是这样

connect by level<=-1也会产生一行,这个要注意

=3不行,必须<=3

SELECT LEVEL,ID,manager_id FROM s_emp

START WITH manager_id IS NULL

CONNECT BY PRIOR ID=manager_id AND LEVEL<=3;

第1条和第2条要理解递归的本质

dingjun123@ORADB> with t as

  2  (select 1 id from dual union all select 2 from dual)

  3  select level

  4  from t

  5  connect by level<3

  6  ;

     LEVEL

----------

         1

         2

         2

         1

         2

         2

已选择6行。

已用时间:  00: 00: 00.01

dingjun123@ORADB> ed

已写入 file afiedt.buf

  1  with t as

  2  (select 1 id from dual union all select 2 from dual)

  3  select level

  4  from t

  5  connect by level<3

  6* and prior dbms_random.value is not null

  7  /

     LEVEL

----------

         1

         2

         2

         1

         2

         2

已选择6行。

已用时间:  00: 00: 00.03

已用时间:  00: 00: 00.01

--加上id自连接,必须加上dbms_random,这样相当于每行单独递归的次数,不向上面一样了

dingjun123@ORADB> ed

已写入 file afiedt.buf

  1  with t as

  2  (select 1 id from dual union all select 2 from dual)

  3  select level

  4  from t

  5  connect by level<3

  6  and prior id = id

  7* and prior dbms_random.value is not null

dingjun123@ORADB> /

     LEVEL

----------

         1

         2

         1

         2

已选择4行。

已用时间:  00: 00: 00.01

dingjun123@ORADB> ed

已写入 file afiedt.buf

  1  with t as

  2  (select 1 id from dual union all select 2 from dual)

  3  select level

  4  from t

  5  connect by level<3

  6* and prior id = id

dingjun123@ORADB> /

ERROR:

ORA-01436: 用户数据中的 CONNECT BY 循环

未选定行

对于connect by,现在大多数人已经很熟悉了

connect by中的条件就表示了父子之间的连接关系

比如 connect by id=prior pid

但如果connect by中的条件没有表示记录之间的父子关系

那会出现什么情况?

常见的,connect by会在构造序列的时候使用

用select rownum from dual connect by rownum<xxx 代替早期版本的 select rownum from all_objects where rownum <xxx

我们注意到,dual是一个只有一条记录的表,如果表有多条记录,将会怎样?

下面开始实验

环境:windows xp sp2 + Oracle 9208

(10.1版本connect by有问题)

CREATE TABLE T

(

  ID  VARCHAR2(1 BYTE)

);

INSERT INTO T ( ID ) VALUES ( 

'A'); 

INSERT INTO T ( ID ) VALUES ( 

'B'); 

INSERT INTO T ( ID ) VALUES ( 

'C'); 

COMMIT;SQL> select id,level from t connect by level<2;

I      LEVEL

- ----------

A          1

B          1

C          1

SQL> select id,level from t connect by level<3;

I      LEVEL

- ----------

A          1

A          2

B          2

C          2

B          1

A          2

B          2

C          2

C          1

A          2

B          2

C          2

已选择12行。

SQL> select id,level from t connect by level<4;

I      LEVEL

- ----------

A          1

A          2

A          3

B          3

C          3

B          2

A          3

B          3

C          3

C          2

A          3

B          3

C          3

B          1

A          2

A          3

B          3

C          3

B          2

A          3

B          3

C          3

C          2

A          3

B          3

C          3

C          1

A          2

A          3

B          3

C          3

B          2

A          3

B          3

C          3

C          2

A          3

B          3

C          3

已选择39行。

复制代码无需多说,我们很快可以找到其中的规律,假设表中有N条记录

则记F(N,l)为 select id,level from t connect by level<l 的结果集数目

那么,

F(N,1)=N

F(N,l) = F(N,l-1)*N+N

于是可以总结出

F(N,l)=∑power(N,p), p取值为[1,l)

要解释,也很容易

当连接条件不能限制记录之间的关系时

每一条记录都可以作为自己或者其他记录的叶子

如下所示:

A          1

A          2

A          3

B          3

C          3

B          2

A          3

B          3

C          3

C          2

A          3

B          3

C          3

在这里,我们看到的是

Oracle采用了深度优先的算法

我们接着看一个例子,看看在SQL中通过connect by如何将任意一个整数(不要太大就行)拆分为若干个power(2,n)的和的方法。

先构造测试数据:

create table ba(n number);

insert into ba select 5*rownum from dual connect by rownum<5;

commit;

select * from ba;

复制代码展示ba中的数据为:

N

-----------------------

5

10

15

20

一个得出结果的简单的SQL为

select distinct a.n , level, bitand(a.n,power(2,level-1)) from ba a connect by level<=floor(log(2,n)+1)

复制代码这里为什么要加distinct?你可以尝试去掉distinct ,看看结果与保持distinct有多大差别。

然后我们先来看,如果只对其中的一条记录进行操作,那么加不加distinct,结果是否是一样的?比如我们只看第一条记录5的拆分结果

select distinct a.n , level, bitand(a.n,power(2,level-1)) from (select * from ba where rownum=1) a connect by level<=floor(log(2,n)+1);

复制代码结果为:

N    LEVEL    BITAND(A.N,POWER(2,LEVEL-1))

----------------------------------------------------------------

5    1             1

5    2             0

5    3             4

复制代码去掉distinct的sql为

select a.n , level, bitand(a.n,power(2,level-1)) from (select * from ba where rownum=1) a connect by level<=floor(log(2,n)+1);

复制代码输出结果,自己运行一下看看。然后你就该思考了,为什么你看到的结果会是这样???

这里不做过多解释,做完上面的实验,然后结合1楼中所说的,我想你应该就能明白了。

———————————————————————我是Long Long Ago的大坑的分界线———————————————————————————

事实上我们有更好的办法来处理:

with a as (select n, floor(log(2,n)+1) lc from ba)

select a.n, bitand(a.n,power(2,b.rn-1)) from a, 

(select rownum rn from

        (select max(lc) mlc from a) 

        connect by level<=mlc

)b

where rn<=a.lc

order by 1,2

复制代码内层SQL先取得所有记录中可拆分出来的power(2,n)中的n最大可能是多少,然后由此构造出序列,最后再做一次关联查询,用限制条件rn<=a.lc限制住每个N中可拆分出来的power(2,n)中的n的最大值,由此可以高效得出结果。

上例实质上与  对多记录按各自指定次数重复  的性质是一样的。

简单总结:

对单记录/单条数据使用connect by,没问题

但对多条记录使用connect by,就会碰到问题,千万要注意。
SQL> with tmp as (select 2 a from dual union all select 3 from dual union all select 4 from dual)
  2  select rownum, b.*
  3    from (select a.a, sum(a.a) over(order by rownum) - rownum + 1 psum
  4            from tmp a) b
  5  connect by rownum <= b.psum;

    ROWNUM          A       PSUM
---------- ---------- ----------
         1          2          2
         2          2          2
         3          3          4
         4          3          4
         5          4          7
         6          4          7
         7          4          7
         8          3          4
         9          4          7

9 rows selected
以上红色部分,实在搞不懂为什么会出现在结果集中。
因为按connect by rownum <= psum的条件,8、9都是大于4、7的。但是却出现在了结果集中,不明白这是何原因。
有谁可以解释一下? 
您只给出了内层的查询,我不明白这是什么意思......
我能明白这个内层查询的含义,但是不能理解外层查询中rownum=8/9的情况下,为何会出现psum=4/7的情况。
因为此时rownum(8/9) > psum(4/7)了,为何会在connect by rownum <= psum的条件下出现这样的结果?
虽然结果是我想要的,但是不明白这是为什么。

实际上,我是想知道,为何数据会是这样展现的?他的过程是怎么样的?

对于结果:
a  b
2  2
3  4
4  7
可以推算,
a=2时,rownum <= 2(b的值),此时rownum=1,则有:
rownum   a    b
1              2    2
2              2    2--直到rownum=2

a=3时,rownum <= 4,此时rownum=3,则有:
rownum   a    b
3              3    4
4              3    4--直到rownum=4

a=3时,rownum <= 7,此时rownum=5,则有:
rownum   a    b
5              4    7
6              4    7
7              4    7--直到rownum=7

于是经过connect by rownum <= psum就可以得到:
1        2        2
2        2        2
3        3        4
4        3        4
5        4        7
6        4        7
7        4        7
8        3        4
9        4        7

但是接下来红色部分的8、9是如何推算的?
rownum   a    b
8              3    4
9              4    7
还是我这样推算是错误的?
原帖由 CaptainKobe 于 2009-12-15 16:32 发表 
SQL> SELECT ROWNUM FROM DUAL CONNECT BY ROWNUM  
你这个是静态的,而且是单条的情况下。
考虑多条,多个rownum限定值时,情况就没有那么简单了。
至于你的rownum<=10为什么有11条,我就不得而知了。应该是10条:
SQL> select rownum from dual connect by rownum <= 10 ;

    ROWNUM
----------
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10

10 rows selected

总结了下规律,发现
不管rownum如何限制,他首先会根据指定的psum值生成若干条数据,直到rownum=这个指定的值时停下,然后转入下一个psum。如rownum=3,而psum=4时,会生成rownum=3和4两条记录。
因此生成的数据为psum-开始时的rownum+1,比如上面的4-3+1=2。
但是,oracle在最后还会根据每个psum自动生成一行,也就是将原始表再复制一次(第一条不复制,不管psum是否有重复都会复制)。
于是生成的记录变成了:4-3+1+1=3了。就是我们所要的行数。

加上LEVEL就明白了:
with tmp as (select 2 a from dual union all select 3 from dual union all select 4 from dual)
select rownum,level, b.*
  from (select a.a, sum(a.a) over(order by rownum) - rownum + 1 psum
          from tmp a) b
connect by rownum <= b.psum;

    ROWNUM      LEVEL          A       PSUM
---------- ---------- ---------- ----------
         1          1          2          2
         2          2          2          2
         3          3          3          4
         4          4          3          4
         5          5          4          7
         6          6          4          7
         7          7          4          7
         8          1          3          4
         9          1          4          7

LEVEL 1是不受CONNECT BY条件限制的。

因为你没有指定START WITH, 所以三行全部都是起点,即结果中你看到的三个LEVEL 1的行。这三行是一定会出来的,不受你CONNECT BY限制。
从2,2起点的结果从LEVEL 1一直到LEVEL 7
其他两行的结果就是你看到的8, 9行,它们没有更高的LEVEL因为从LEVEL 2开始已经不满足CONNECT BY条件,遍历就终止了。
我大概看明白你的意思了。
2  2
3  4
4  7
是不是可以这样理解,我开始查询的时候,rownum=1。然后由于connect by rownum <= 2,于是生成两条记录。
即:
rownum  a   b
1             2   2
2             2   2
然后,此时rownum=2,rownum再与4比较,发现比4小。于是再生成记录,直到=4为止,即:
rownum  a   b
1             2   2
2             2   2
3             3   4
4             3   4
然后,此时rownum=4,再与7比较,发现比7小。于是再生成记录,直到=7为止,即:
rownum  a   b
1             2   2
2             2   2
3             3   4
4             3   4
5             4   7
6             4   7
7             4   7
最后发现第一轮已经轮询完了,然后转入第二轮,由于没有指定start with,
所以接下来的数据都只生成一条,其他的rownum条件都已经不满足rownum<=psum的条件了

理解正确。
CONNECT BY一般是要写前后关系的,即 PRIOR 列名1 = 列名2
没有这个关系的用法经常是在表中只有一行的情况,(比如DUEL),然后用ROWNUM或LEVEL来控制输出的行数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: