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

来自兔子大神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来控制输出的行数。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值