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是一个只有一条记录的表,如果表有多条记录,将会怎样?

下面开始实验

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;
N
-------
5
10
15
20

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

  1. 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);

结果为:

  1. N    LEVEL    BITAND(A.N,POWER(2,LEVEL-1))
  2. ----------------------------------------------------------------
  3. 5    1             1
  4. 5    2             0
  5. 5    3             4

去掉distinct的sql为

  1. 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楼中所说的,我想你应该就能明白了。

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

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,就会碰到问题,千万要注意。

elect rownum,
level,
sys_connect_by_path(id, ',') path,
id,
connect_by_isleaf isleaf
from t
connect by nocycle level < 2
order by rownum, level, path; select rownum,
level,
sys_connect_by_path(id, ',') path,
id,
connect_by_isleaf isleaf
from t
connect by nocycle level < 3
order by rownum, level, path; select rownum,
level,
sys_connect_by_path(id, ',') path,
id,
connect_by_isleaf isleaf
from t
connect by nocycle level < 4
order by rownum, level, path; 下面是执行结果:
CHENCH@orcl> select rownum,
2 level,
3 sys_connect_by_path(id, ',') path,
4 id,
5 connect_by_isleaf isleaf
6 from t
7 connect by nocycle level < 2
8 order by rownum, level, path; ROWNUM LEVEL PATH ID ISLEAF
---------- ---------- ---------- -- ----------
1 1 ,A A 1
2 1 ,B B 1
3 1 ,C C 1 Elapsed: 00:00:00.01
CHENCH@orcl>
CHENCH@orcl> select rownum,
2 level,
3 sys_connect_by_path(id, ',') path,
4 id,
5 connect_by_isleaf isleaf
6 from t
7 connect by nocycle level < 3
8 order by rownum, level, path; ROWNUM LEVEL PATH ID ISLEAF
---------- ---------- ---------- -- ----------
1 1 ,A A 0
2 2 ,A,A A 1
3 2 ,A,B B 1
4 2 ,A,C C 1
5 1 ,B B 0
6 2 ,B,A A 1
7 2 ,B,B B 1
8 2 ,B,C C 1
9 1 ,C C 0
10 2 ,C,A A 1
11 2 ,C,B B 1 ROWNUM LEVEL PATH ID ISLEAF
---------- ---------- ---------- -- ----------
12 2 ,C,C C 1 12 rows selected. Elapsed: 00:00:00.01
CHENCH@orcl>
CHENCH@orcl> select rownum,
2 level,
3 sys_connect_by_path(id, ',') path,
4 id,
5 connect_by_isleaf isleaf
6 from t
7 connect by nocycle level < 4
8 order by rownum, level, path; ROWNUM LEVEL PATH ID ISLEAF
---------- ---------- ---------- -- ----------
1 1 ,A A 0
2 2 ,A,A A 0
3 3 ,A,A,A A 1
4 3 ,A,A,B B 1
5 3 ,A,A,C C 1
6 2 ,A,B B 0
7 3 ,A,B,A A 1
8 3 ,A,B,B B 1
9 3 ,A,B,C C 1
10 2 ,A,C C 0
11 3 ,A,C,A A 1 ROWNUM LEVEL PATH ID ISLEAF
---------- ---------- ---------- -- ----------
12 3 ,A,C,B B 1
13 3 ,A,C,C C 1
14 1 ,B B 0
15 2 ,B,A A 0
16 3 ,B,A,A A 1
17 3 ,B,A,B B 1
18 3 ,B,A,C C 1
19 2 ,B,B B 0
20 3 ,B,B,A A 1
21 3 ,B,B,B B 1
22 3 ,B,B,C C 1 ROWNUM LEVEL PATH ID ISLEAF
---------- ---------- ---------- -- ----------
23 2 ,B,C C 0
24 3 ,B,C,A A 1
25 3 ,B,C,B B 1
26 3 ,B,C,C C 1
27 1 ,C C 0
28 2 ,C,A A 0
29 3 ,C,A,A A 1
30 3 ,C,A,B B 1
31 3 ,C,A,C C 1
32 2 ,C,B B 0
33 3 ,C,B,A A 1 ROWNUM LEVEL PATH ID ISLEAF
---------- ---------- ---------- -- ----------
34 3 ,C,B,B B 1
35 3 ,C,B,C C 1
36 2 ,C,C C 0
37 3 ,C,C,A A 1
38 3 ,C,C,B B 1
39 3 ,C,C,C C 1 39 rows selected. Elapsed: 00:00:00.04
关键是 connect by 后面不管是level 还是 rownum都是在查询结果集内作的限制

SQL> with t as (
2 select 1 from dual
3 union all
4 select 2 from dual
5 union all
6 select 3 from dual)
7 select * from t connect by rownum < 5; 1
----------
1
1
1
1
2
3 已选择6行。 SQL> with t as (select 1 from dual)
2 select * from t connect by rownum < 5; 1
----------
1
1
1
1 已选择4行。
with a as (
select 5 as n from dual
union all
select 10 from dual
union all
select 15 from dual
union all
select 20 from dual
)
select distinct a.n , level, bitand(a.n,power(2,level-1)) from a connect by level<=floor(log(2,n)+1); SQL> with a as (
2 select 5 as n from dual
3 union all
4 select 10 from dual
5 union all
6 select 15 from dual
7 union all
8 select 20 from dual
9 )
10 select distinct a.n , level, bitand(a.n,power(2,level-1)) from a connect by level<=floor(log(2,n)+1); N LEVEL BITAND(A.N,POWER(2,LEVEL-1))
---------- ---------- ----------------------------
10 4 8
15 2 2
20 2 0
20 4 0
15 3 4
5 1 1
10 3 0
10 1 0
20 3 4
5 2 0
20 5 16
10 2 2
5 3 4
15 4 8
15 1 1
20 1 0 已选择16行。
SQL> with a as (
2 select 5 as n from dual
3 union all
4 select 10 from dual
5 union all
6 select 15 from dual
7 union all
8 select 20 from dual
9 )
10 select distinct a.n , level, bitand(a.n,power(2,level-1)) from (select * from a 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 已选择3行。 SQL> with a as (
2 select 5 as n from dual
3 union all
4 select 10 from dual
5 union all
6 select 15 from dual
7 union all
8 select 20 from dual
9 )
10 select a.n , level, bitand(a.n,power(2,level-1)) from (select * from a 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 已选择3行。
SQL>    with a as (
2 select 5 as n from dual
3 union all
4 select 10 from dual
5 union all
6 select 15 from dual
7 union all
8 select 20 from dual
9 )
10 select * from a where a.n=5 connect by rownum<6; N
----------
5
5
5
5
5
SQL>    with a as (
2 select 5 as n from dual
3 union all
4 select 10 from dual
5 union all
6 select 15 from dual
7 union all
8 select 20 from dual
9 )
10 select * from a where rownum=1 connect by rownum<6;
ERROR:
ORA-30009: CONNECT BY 操作内存不足
 with a as (
select 5 as n from dual
union all
select 10 from dual
union all
select 15 from dual
union all
select 20 from dual
)
select * from a where a.n=5 connect by level<6;
5
5
5
5
5
5
5
5
5
5 已选择341行。

Oracle的Connect By理解的更多相关文章

  1. oracle中 connect by prior 递归算法 -- 理解

    oracle中 connect by prior 递归算法 -- 理解 http://blog.163.com/xxciof/blog/static/7978132720095193113752/  ...

  2. oracle使用connect by进行级联查询 树型菜单

    Oracle使用connect by进行级联查询 树型菜单(转) connect by可以用于级联查询,常用于对具有树状结构的记录查询某一节点的所有子孙节点或所有祖辈节点. 来看一个示例,现假设我们拥 ...

  3. 12C 连接方式和 Oracle Easy Connect Naming method

    1.12C 连接方式 PDB is not an instance, so using SID in the connection string will not work. When the dat ...

  4. mysql实现ORACLE的connect by prior父子递归查询

    oracle中有connect by prior ,可以实现父子递归查询.而mysql中没有这种功能,但我们可以变通实现. 比如一个表: Table Name: tb_Tree Id | Parent ...

  5. oracle 分页(rownum的理解) 以及 树节点的查询

    1:什么是rownum, rownum的生成, rownum相关的符号操作 Rownum是oracle生成结果集时得到的一个伪列, 按照读出行的顺序, 第一条rownum=1, 第二条=2. 对于 O ...

  6. ORACLE中CONNECT BY...START WITH...的使用

    源: https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm http://www.cnblogs.com/baiy ...

  7. oracle中connect by语句的优化

    很多应用中都会有类似组织机构的表,组织机构的表又通常是典型的层次结构(没有循环节点).于是通过组织控制数据权限的时候,许多人都喜欢通过connect by获得组织信息,然后再过滤目标数据. 在有些情况 ...

  8. ORACLE的CONNECT和RESOURCE角色权限

    最近在处理数据库的用户权限问题,之前惯性思维,觉得给用户授权RESOURCE权限之后,用户的一般权限都会有,等到发现用户有RESOURCE角色,却没有创建视图的权限之后,才发现这部分还是一知半解啊,所 ...

  9. oracle中 connect by prior 递归算法

    Oracle中start with...connect by prior子句用法 connect by 是结构化查询中用到的,其基本语法是: select ... from tablename sta ...

随机推荐

  1. unity update 和fixedudpate

    但是Update会在每次渲 染新的一帧时被调用. 而FixedUpdate会在每个固定的时间间隔被调用,

  2. Windows7下安装MongoDB

    1.下载地址:http://www.mongodb.org/downloads(32位还是64位自行选择).我下载的是:mongodb-win32-x86_64-2.4.5.zip 2.解压把mong ...

  3. UVa 10870 & 矩阵快速幂

    题意: 求一个递推式(不好怎么概括..)的函数的值. 即 f(n)=a1f(n-1)+a2f(n-2)+...+adf(n-d); SOL: 根据矩阵乘法的定义我们可以很容易地构造出矩阵,每次乘法即可 ...

  4. CentOS6.4 访问域局网中Windows的共享

    mount -t cifs -o username=" //10.10.3.246/f /usr/local/openresty/nginx/html/down 说明: mount -t c ...

  5. javascript 函数及作用域总结介绍

    在js中使用函数注意三点: 1.函数被调用时,它是运行在他被声明时的语法环境中的: 2.函数自己无法运行,它总是被对象调用的,函数运行时,函数体内的this指针指向调用该函数的对象,如果调用函数时没有 ...

  6. [深入浅出WP8.1(Runtime)]数据绑定的基础

    11.1 数据绑定的基础 数据绑定是一种XAML界面和后台数据通信的方式,因为界面和后台数据的通信的场景有多种,并且数据于数据之间也存在着不一样的关联关系,所以数据绑定的实现技巧和方式也是多种多样的. ...

  7. 【BZOJ】2286: [Sdoi2011消耗战

    http://www.lydsy.com/JudgeOnline/problem.php?id=2286 题意:n个点的边加权树,m个询问,每次询问给出的k个点与结点1分离的最小代价.(n<=2 ...

  8. [BZOJ2795][Poi2012]A Horrible Poem

    2795: [Poi2012]A Horrible Poem Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 261  Solved: 150[Subm ...

  9. 热烈庆祝华清远见2014嵌入式系统(Linux&Android)开发就业培训课程全面升级

    近日,华清远见公开宣布:2014嵌入式系统 (Linux&Android)开发就业培训课程再次升级!据悉,华清远见如今已经持续10年,一直保持课程每年2次的更新的频率.华清远见的每 次课程更新 ...

  10. viso 由于形状保护和/或图层属性设置不能进行编辑

    viso 由于形状保护和/或图层属性设置不能进行编辑 2003: 若要变通解决此问题,删除 从删除 的保护属性,当您尝试删除一个受保护的组件.若要这样做,请按照下列步骤操作:在 Visio 2003或 ...