|
本帖最后由 谁 于 2011-10-28 23:59 编辑
我们接着看一个例子,看看在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,就会碰到问题,千万要注意。
[ 本帖最后由 谁 于 2008-7-3 12:47 编辑 ] |
|