楼主: tree_new_bee

递归with真是个好东西

[复制链接]
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
21#
发表于 2010-12-10 21:25 | 只看该作者
6小时了,还没动静
SQL> with t as (
  2  select level*10 n from dual connect by level<=1E6)
  3  ,t1 as (select n n1, lead(n ,1) over (order by n desc) n2 from t )
  4  ,t2 as (select max(n1) n1, max(n2)n2  from t1 )
  5  , mgcd(a,b, a2, b2) as
  6  (select n1, n2, n1, n2 from t2
  7  union all
  8  select
  9  case when b2=0 then (select max(n) from t where n<a) else a end,
10  case when b2=0 then a2 else b end,
11  case when b2=0 then (select max(n) from t where n<a) else b2 end,
12  case when b2=0 then  a2 else mod(a2, b2) end
13  from mgcd where a is not null
14  )
15  cycle a,b,a2,b2 set iscycle to 'y' default 'n'
16  select min(a2) from mgcd where b2=0
17
SQL> /

又找到1个测试机器的好东西

使用道具 举报

回复
论坛徽章:
10
CTO参与奖
日期:2009-02-20 09:44:20ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30迷宫蛋
日期:2012-05-07 10:55:58茶鸡蛋
日期:2012-04-19 16:08:262012新春纪念徽章
日期:2012-01-04 11:54:462011新春纪念徽章
日期:2011-01-04 10:24:02数据库板块每日发贴之星
日期:2010-12-19 01:01:02数据库板块每日发贴之星
日期:2010-12-13 01:01:012009日食纪念
日期:2009-07-22 09:30:00优秀写手
日期:2014-02-08 06:00:12
22#
 楼主| 发表于 2010-12-10 21:58 | 只看该作者
原帖由 〇〇 于 2010-12-10 21:25 发表
6小时了,还没动静
SQL> with t as (
  2  select level*10 n from dual connect by level


你跟机器有仇啊?


1E6,我这里直接报内存不够。大概是pga太小。
5E3, 要9秒
1E4, 要35秒。
2E4, 要130秒
看样子参数加大一倍, 时间要4倍。 照这么推算, 1E5, 估计要一个小时。1E6如果不报错则要1000个小时, 也就是40天吧!

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
23#
发表于 2010-12-10 22:33 | 只看该作者
我写的:

最小公倍数:
WITH n AS (
SELECT 4 n FROM DUAL
UNION ALL SELECT 9 FROM DUAL
UNION ALL SELECT 6 FROM DUAL
UNION ALL SELECT 15 FROM DUAL
)
,n2 AS (SELECT ROWNUM id,COUNT(*) OVER() cnt,n FROM n)
,t (id,cnt,val,a,b,lcm) AS (
  SELECT id,cnt,n,0,1,n FROM n2 WHERE id=1
  UNION ALL
  SELECT DECODE(t.a,0,t.id+1,t.id)
        ,t.cnt
        ,n2.n
        ,DECODE(t.a,0,n2.n,MOD(t.b,t.a))
        ,DECODE(t.a,0,t.lcm,t.a)
         END
        ,DECODE(mod(t.b,t.a),0,t.lcm*t.val/t.a,t.lcm)
    FROM t,n2
   WHERE (t.id<t.cnt OR t.id=t.cnt AND t.a<>0)
         AND DECODE(t.a,0,t.id+1,t.id) = n2.id
)
SELECT lcm FROM t WHERE a=0 AND id=cnt;



       LCM
----------
       180


最大公约数:
WITH n AS (
SELECT 20 n FROM DUAL
UNION ALL SELECT 16 FROM DUAL
UNION ALL SELECT 18 FROM DUAL
UNION ALL SELECT 12 FROM DUAL
)
,n2 AS (SELECT ROWNUM id,COUNT(*) OVER() cnt,n FROM n)
,t (id,cnt,val,a,b,gcd) AS (
  SELECT id,cnt,n,0,1,n FROM n2 WHERE id=1
  UNION ALL
  SELECT DECODE(t.a,0,t.id+1,t.id)
        ,t.cnt
        ,n2.n
        ,DECODE(t.a,0,n2.n,MOD(t.b,t.a))
        ,DECODE(t.a,0,t.gcd,t.a)
        ,DECODE(mod(t.b,t.a),0,t.a,t.gcd)
    FROM t,n2
   WHERE (t.id<t.cnt OR t.id=t.cnt AND t.a<>0)
         AND DECODE(t.a,0,t.id+1,t.id) = n2.id
)
SELECT gcd FROM t WHERE a=0 AND id=cnt;


       GCD
----------
         2

如果是连续自然数则集合n可以忽略,下面是1~1E6的GCD:
WITH t (id,a,b,gcd) AS (
  SELECT 1,0,1,1 FROM DUAL
  UNION ALL
  SELECT DECODE(t.a,0,t.id+1,t.id)
        ,DECODE(t.a,0,t.id+1,MOD(t.b,t.a))
        ,DECODE(t.a,0,t.gcd,t.a)
        ,DECODE(mod(t.b,t.a),0,t.a,t.gcd)
    FROM t
   WHERE (t.id<1E6 OR t.id=1E6 AND t.a<>0)
)
SELECT gcd FROM t WHERE a=0 AND id=1E6;



       GCD
----------
         1

Elapsed: 00:01:43.66

当然这没什么意思。

我在新出的书中有一章专门写这个递归WITH(包括那个斐波那契数), 另外还有很多例子散落在论坛的回帖中。

[ 本帖最后由 newkid 于 2010-12-11 03:59 编辑 ]

使用道具 举报

回复
论坛徽章:
10
CTO参与奖
日期:2009-02-20 09:44:20ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30迷宫蛋
日期:2012-05-07 10:55:58茶鸡蛋
日期:2012-04-19 16:08:262012新春纪念徽章
日期:2012-01-04 11:54:462011新春纪念徽章
日期:2011-01-04 10:24:02数据库板块每日发贴之星
日期:2010-12-19 01:01:02数据库板块每日发贴之星
日期:2010-12-13 01:01:012009日食纪念
日期:2009-07-22 09:30:00优秀写手
日期:2014-02-08 06:00:12
24#
 楼主| 发表于 2010-12-11 09:36 | 只看该作者
原帖由 newkid 于 2010-12-10 22:33 发表
我写的:

最小公倍数:


好!
lcm(a,b) = a*b/gcd(a,b)
lcm(a,b,c) = lcm(lcm(a,b), c) = lcm(a,b) * c / gcd(lcm(a,b), c)

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
25#
发表于 2010-12-11 11:04 | 只看该作者
关于这个gcd,lcm,如果你想自虐的话,我建议你再用MODEL写一遍

使用道具 举报

回复
论坛徽章:
10
CTO参与奖
日期:2009-02-20 09:44:20ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30迷宫蛋
日期:2012-05-07 10:55:58茶鸡蛋
日期:2012-04-19 16:08:262012新春纪念徽章
日期:2012-01-04 11:54:462011新春纪念徽章
日期:2011-01-04 10:24:02数据库板块每日发贴之星
日期:2010-12-19 01:01:02数据库板块每日发贴之星
日期:2010-12-13 01:01:012009日食纪念
日期:2009-07-22 09:30:00优秀写手
日期:2014-02-08 06:00:12
26#
 楼主| 发表于 2010-12-11 14:12 | 只看该作者
原帖由 newkid 于 2010-12-11 11:04 发表
关于这个gcd,lcm,如果你想自虐的话,我建议你再用MODEL写一遍


哈,又布置作业了。

with还没玩够, 先不急着玩model, 看着model 不如with舒服。

使用道具 举报

回复
论坛徽章:
10
CTO参与奖
日期:2009-02-20 09:44:20ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30迷宫蛋
日期:2012-05-07 10:55:58茶鸡蛋
日期:2012-04-19 16:08:262012新春纪念徽章
日期:2012-01-04 11:54:462011新春纪念徽章
日期:2011-01-04 10:24:02数据库板块每日发贴之星
日期:2010-12-19 01:01:02数据库板块每日发贴之星
日期:2010-12-13 01:01:012009日食纪念
日期:2009-07-22 09:30:00优秀写手
日期:2014-02-08 06:00:12
27#
 楼主| 发表于 2010-12-11 14:30 | 只看该作者
用上面的菲波纳契数列解euler project第2题(用通项公式就没意思了)

Find the sum of all the even-valued terms in the sequence which do not exceed four million.

WITH t(a,b) AS (
SELECT 0,1 FROM DUAL
UNION ALL
SELECT b
      ,a+b
  FROM t
WHERE a+b<4000000
)
select sum(b) from t where mod(b,2)=0

SQL> /

    SUM(B)
----------
   4613732

Executed in 0.032 seconds

这个还可以改进:
通过观察fab数列,可以知道: 偶fab数每隔2个出现一个, 所以可以计算如下:
f(n) = f(n-1) + f(n-2)
= f(n-2) + f(n-3) + f(n-3) + f(n-4)
= 2*(f(n-3) + f(n-2) ) + f(n-4)
= 3* f(n-3) + 2*f(n-4)
= 3* f(n-3) + f(n-4) + f(n-5) + f(n-6))
= 4 * f(n-3) + f(n-6)

这样,优化的结果是:
WITH t(a,b) AS (
SELECT 0,2 FROM DUAL
UNION ALL
SELECT b
      ,a+4*b
  FROM t
WHERE a+4*b<4000000
)
select sum(b) from t


SQL> /

    SUM(B)
----------
   4613732

Executed in 0.016 seconds


不过,优化实际上没什么实质效果,两个语句在number精度范围内的任何数上运行,都几乎是同样的常数时间。

[ 本帖最后由 tree_new_bee 于 2010-12-11 14:31 编辑 ]

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
28#
发表于 2010-12-12 13:43 | 只看该作者
newkid的gcd
SQL> WITH n AS (
  2  select level*10 n from dual connect by level <=1e4
  3  )
  4  ,n2 AS (SELECT ROWNUM id,COUNT(*) OVER() cnt,n FROM n)
  5  ,t (id,cnt,val,a,b,gcd) AS (
  6    SELECT id,cnt,n,0,1,n FROM n2 WHERE id=1
  7    UNION ALL
  8    SELECT DECODE(t.a,0,t.id+1,t.id)
  9          ,t.cnt
10          ,n2.n
11          ,DECODE(t.a,0,n2.n,MOD(t.b,t.a))
12          ,DECODE(t.a,0,t.gcd,t.a)
13          ,DECODE(mod(t.b,t.a),0,t.a,t.gcd)
14      FROM t,n2
15     WHERE (t.id<t.cnt OR t.id=t.cnt AND t.a<>0)
16           AND DECODE(t.a,0,t.id+1,t.id) = n2.id
17  )
18  SELECT gcd FROM t WHERE a=0 AND id=cnt;

       GCD
----------
        10

已用时间:  00: 00: 40.19

tnb的
SQL> with t as (
  2  select level*10 n from dual connect by level<=1E4)
  3  ,t1 as (select n n1, lead(n ,1) over (order by n desc) n2 from t )
  4  ,t2 as (select max(n1) n1, max(n2)n2  from t1 )
  5  , mgcd(a,b, a2, b2) as
  6  (select n1, n2, n1, n2 from t2
  7  union all
  8  select
  9  case when b2=0 then (select max(n) from t where n<a) else a end,
10  case when b2=0 then a2 else b end,
11  case when b2=0 then (select max(n) from t where n<a) else b2 end,
12  case when b2=0 then  a2 else mod(a2, b2) end
13  from mgcd where a is not null
14  )
15  cycle a,b,a2,b2 set iscycle to 'y' default 'n'
16  select min(a2) from mgcd where b2=0;

   MIN(A2)
----------
        10

已用时间:  00: 00: 21.92

SQL> 2
  2* select level*10 n from dual connect by level<=1E4)
SQL> c/1E/2E
  2* select level*10 n from dual connect by level<=2E4)
SQL> /

   MIN(A2)
----------
        10

已用时间:  00: 01: 26.16
SQL> 2
  2* select level*10 n from dual connect by level<=2E4)
SQL> c/2E/4E
  2* select level*10 n from dual connect by level<=4E4)
SQL> /

   MIN(A2)
----------
        10

已用时间:  00: 05: 45.83
SQL> 2
  2* select level*10 n from dual connect by level<=4E4)
SQL> c/4E/16E
  2* select level*10 n from dual connect by level<=16E4)
SQL> /

   MIN(A2)
----------
        10

已用时间:  01: 29: 33.37
SQL>

[ 本帖最后由 〇〇 于 2010-12-13 07:35 编辑 ]

使用道具 举报

回复
论坛徽章:
10
CTO参与奖
日期:2009-02-20 09:44:20ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30迷宫蛋
日期:2012-05-07 10:55:58茶鸡蛋
日期:2012-04-19 16:08:262012新春纪念徽章
日期:2012-01-04 11:54:462011新春纪念徽章
日期:2011-01-04 10:24:02数据库板块每日发贴之星
日期:2010-12-19 01:01:02数据库板块每日发贴之星
日期:2010-12-13 01:01:012009日食纪念
日期:2009-07-22 09:30:00优秀写手
日期:2014-02-08 06:00:12
29#
 楼主| 发表于 2010-12-12 16:43 | 只看该作者
原帖由 〇〇 于 2010-12-10 21:25 发表
6小时了,还没动静


OO, 前面测那个, 等到最终结果了吗?  多少时间?

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
30#
发表于 2010-12-12 17:23 | 只看该作者
原帖由 tree_new_bee 于 2010-12-12 16:43 发表


OO, 前面测那个, 等到最终结果了吗?  多少时间?

还在执行看不到结果

plan.jpg (64.74 KB, 下载次数: 36)

plan.jpg

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表