楼主: 〇〇

[转载] 趣味题

[复制链接]
论坛徽章:
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
51#
 楼主| 发表于 2010-6-11 07:44 | 只看该作者

拆成2步

SQL> create table t AS (SELECT REPLACE(SYS_CONNECT_BY_PATH(rn,','),',') x
  2               FROM (SELECT to_char(ROWNUM-1,'fmx') rn FROM DUAL CONNECT BY ROWNUM<=16)
  3              WHERE LEVEL=4
  4              CONNECT BY NOCYCLE rn<> PRIOR rn AND LEVEL<=4
  5            );

表已创建。

已用时间:  00: 00: 00.57
SQL> select count(*)from t;

  COUNT(*)
----------
     43680

已用时间:  00: 00: 00.01
SQL> exec DBMS_STATS.GATHER_TABLE_STATS('LT','T');

PL/SQL 过程已成功完成。

已用时间:  00: 00: 00.12
SQL> explain plan for select count(*) from(
  2  select a.x||'+'||b.x||'+'||c.x||'='||to_char(to_number(a.x,'fmxxxx')+to_number(b.x,'fmxxxx')+to_number(c.x,'fmxxxx'),'fmxxxx')s
  3  from t a,t b,t c
  4  where to_number(a.x,'fmxxxx')<to_number('8000','fmxxxx')
  5        and to_number(a.x,'fmxxxx')<to_number(b.x,'fmxxxx')
  6        and to_number(b.x,'fmxxxx')<to_number(c.x,'fmxxxx')
  7        AND to_number(a.x,'fmxxxx')+to_number(b.x,'fmxxxx')+to_number(c.x,'fmxxxx') <=to_number('fedc','fmxxxx')
  8        and translate('0123456789abcdef','$'||a.x||b.x||to_char(to_number(a.x,'fmxxxx')+to_number(b.x,'fmxxxx')+to_number(c.x,'fmxx
xx'),'fmxxxx'),'$') is null
  9        );

已解释。

已用时间:  00: 00: 00.00
SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 4206735519

-------------------------------------------------------------------------------
| Id  | Operation              | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |      |     1 |    15 | 31960 (100)| 00:06:24 |
|   1 |  SORT AGGREGATE        |      |     1 |    15 |            |          |
|   2 |   MERGE JOIN           |      |    26M|   372M| 31960 (100)| 00:06:24 |
|   3 |    SORT JOIN           |      |  4769K|    45M|    63  (31)| 00:00:01 |
|   4 |     MERGE JOIN         |      |  4769K|    45M|    63  (31)| 00:00:01 |
|   5 |      SORT JOIN         |      | 43680 |   213K|    24   (9)| 00:00:01 |
|   6 |       TABLE ACCESS FULL| T    | 43680 |   213K|    22   (0)| 00:00:01 |
|*  7 |      SORT JOIN         |      |  2184 | 10920 |    24   (9)| 00:00:01 |
|*  8 |       TABLE ACCESS FULL| T    |  2184 | 10920 |    23   (5)| 00:00:01 |
|*  9 |    FILTER              |      |       |       |            |          |
|* 10 |     SORT JOIN          |      | 43680 |   213K|    24   (9)| 00:00:01 |
|  11 |      TABLE ACCESS FULL | T    | 43680 |   213K|    22   (0)| 00:00:01 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   7 - access(TO_NUMBER("A"."X",'fmxxxx')<TO_NUMBER("B"."X",'fmxxxx'))
       filter(TO_NUMBER("A"."X",'fmxxxx')<TO_NUMBER("B"."X",'fmxxxx'))
   8 - filter(TO_NUMBER("A"."X",'fmxxxx')<TO_NUMBER('8000','fmxxxx'))
   9 - filter(TO_NUMBER("A"."X",'fmxxxx')+TO_NUMBER("B"."X",'fmxxxx')+TO
              _NUMBER("C"."X",'fmxxxx')<=TO_NUMBER('fedc','fmxxxx') AND
              TRANSLATE('0123456789abcdef','$'||"A"."X"||"B"."X"||TO_CHAR(TO_NUMBER("A
              "."X",'fmxxxx')+TO_NUMBER("B"."X",'fmxxxx')+TO_NUMBER("C"."X",'fmxxxx'),
              'fmxxxx'),'$') IS NULL)
  10 - access(TO_NUMBER("B"."X",'fmxxxx')<TO_NUMBER("C"."X",'fmxxxx'))
       filter(TO_NUMBER("B"."X",'fmxxxx')<TO_NUMBER("C"."X",'fmxxxx'))

已选择32行。

已用时间:  00: 00: 00.04

使用道具 举报

回复
论坛徽章:
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
52#
 楼主| 发表于 2010-6-11 08:48 | 只看该作者
为什么connect_by_path算出来的t记录要多3000多?

SQL> set timi on
SQL> set lines 132 pages 50000
SQL> with t as(select x from (select to_char(level-1,'fmxxxx') x from dual connect by level<=65536)
  2  where substr(x,1,1)<>substr(x,2,1) and  substr(x,1,1)<>substr(x,3,1) and  substr(x,1,1)<>substr(x,4,1)
  3  and substr(x,2,1)<>substr(x,3,1) and substr(x,2,1)<>substr(x,4,1) and substr(x,3,1)<>substr(x,4,1)
  4  )
  5  select count(*) from t;

  COUNT(*)
----------
     40950

已用时间:  00: 00: 00.21
SQL> with t as(select x from (select to_char(level-1,'fmxxxx') x from dual connect by level<=65536)
  2  where substr(x,1,1)<>substr(x,2,1) and  substr(x,1,1)<>substr(x,3,1) and  substr(x,1,1)<>substr(x,4,1)
  3  and substr(x,2,1)<>substr(x,3,1) and substr(x,2,1)<>substr(x,4,1) and substr(x,3,1)<>substr(x,4,1)
  4  )
  5  select sum(length(x))/4 from t;

SUM(LENGTH(X))/4
----------------
           40950

已用时间:  00: 00: 00.21

---

SQL> create table t AS (SELECT REPLACE(SYS_CONNECT_BY_PATH(rn,','),',') x
  2               FROM (SELECT to_char(ROWNUM-1,'fmx') rn FROM DUAL CONNECT BY ROWNUM<=16)
  3              WHERE LEVEL=4
  4              CONNECT BY NOCYCLE rn<> PRIOR rn AND LEVEL<=4
  5            );

表已创建。

已用时间:  00: 00: 00.57
SQL> select count(*)from t;

  COUNT(*)
----------
     43680

是自己写错了,速度还是不用connect_by_path快

SQL> with t as(select x from (select to_char(level-1,'fm0xxx') x from dual connect by level<=65536)
  2  where substr(x,1,1)<>substr(x,2,1) and  substr(x,1,1)<>substr(x,3,1) and  substr(x,1,1)<>substr(x,4,1)
  3  and substr(x,2,1)<>substr(x,3,1) and substr(x,2,1)<>substr(x,4,1) and substr(x,3,1)<>substr(x,4,1)
  4  )
  5  select count(*) from t;

  COUNT(*)
----------
     43680

已用时间:  00: 00: 00.21
SQL> with t AS (SELECT REPLACE(SYS_CONNECT_BY_PATH(rn,','),',') x
  2     FROM (SELECT to_char(ROWNUM-1,'fmx') rn FROM DUAL CONNECT BY ROWNUM<=16)
  3    WHERE LEVEL=4
  4    CONNECT BY NOCYCLE rn<> PRIOR rn AND LEVEL<=4
  5  )
  6  select count(*) from t;

  COUNT(*)
----------
     43680

已用时间:  00: 00: 00.42
SQL>
SQL> /

  COUNT(*)
----------
     43680

已用时间:  00: 00: 00.40
SQL>

[ 本帖最后由 〇〇 于 2010-6-11 08:54 编辑 ]

使用道具 举报

回复
论坛徽章:
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
53#
 楼主| 发表于 2010-6-11 10:01 | 只看该作者
修改后问题规模太大了
改成2个16进制数相加等于第3个也出不来
SQL> select count(*) from(
  2  select a.x||'+'||b.x||'='||to_char(to_number(a.x,'fm0xxx')+to_number(b.x,'fm0xxx'),'fm0xxx')s
  3  from t a,t b --,t c
  4  where to_number(a.x,'fm0xxx')<to_number('8000','fm0xxx')
  5        and to_number(a.x,'fm0xxx')<to_number(b.x,'fm0xxx')
  6        AND to_number(a.x,'fm0xxx')+to_number(b.x,'fm0xxx') <=to_number('fedc','fm0xxx')
  7        and translate('0123456789abcdef','$'||a.x||b.x||to_char(to_number(a.x,'fm0xxx')+to_number(b.x,'fm0xxx')),'$') is null
  8        );
^C

使用道具 举报

回复
论坛徽章:
1088
金色在线徽章
日期:2007-04-25 04:02:08金色在线徽章
日期:2007-06-29 04:02:43金色在线徽章
日期:2007-03-11 04:02:02在线时间
日期:2007-04-11 04:01:02在线时间
日期:2007-04-12 04:01:02在线时间
日期:2007-03-07 04:01:022008版在线时间
日期:2010-05-01 00:01:152008版在线时间
日期:2011-05-01 00:01:342008版在线时间
日期:2008-06-03 11:59:43ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30
54#
发表于 2010-6-11 10:19 | 只看该作者
鼓励研究和分享精神,希望大家多研究多总结,这样才能相互提高!

使用道具 举报

回复
论坛徽章:
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
55#
 楼主| 发表于 2010-6-11 11:04 | 只看该作者
对not exists来说a+b-c=0的写法影响不大

SQL> with t as(select x from (select level+122 x from dual connect by level<=(987-122)) where substr(x,1,1)<>substr(x,2,1) and
  2  substr(x,1,1)<>substr(x,3,1)
  3  and  substr(x,2,1)<>substr(x,3,1) and instr(x,0)=0),
  4  a as (select rownum rn,x from t where x<494)
  5  select count(*) from (
  6  select a.x||'+'||b.x||'-'||c.x||'==0' from a a,t b,t c
  7  where a.x+b.x=c.x and a.x<494 and a.x<b.x --and b.x<c.x
  8  and not exists(select 1 from (select rownum l from dual connect by level<=9)where instr(a.x||b.x||c.x ,l,1,2)>0))
  9  ;

  COUNT(*)
----------
       168

已用时间:  00: 00: 07.00
SQL>
SQL> with t as(select x from (select level+122 x from dual connect by level<=(987-122)) where substr(x,1,1)<>substr(x,2,1) and
  2  substr(x,1,1)<>substr(x,3,1)
  3  and  substr(x,2,1)<>substr(x,3,1) and instr(x,0)=0),
  4  a as (select rownum rn,x from t where x<494)
  5  select count(*) from (
  6  select a.x||'+'||b.x||'-'||c.x||'==0' from a a,t b,t c
  7  where a.x+b.x=c.x and a.x<494 and a.x<b.x and b.x<c.x
  8  and not exists(select 1 from (select rownum l from dual connect by level<=9)where instr(a.x||b.x||c.x ,l,1,2)>0))
  9  ;

  COUNT(*)
----------
       168

已用时间:  00: 00: 07.03
SQL>
SQL> with t as(select x from (select level+122 x from dual connect by level<=(987-122)) where substr(x,1,1)<>substr(x,2,1) and
  2  substr(x,1,1)<>substr(x,3,1)
  3  and  substr(x,2,1)<>substr(x,3,1) and instr(x,0)=0),
  4  a as (select rownum rn,x from t where x<494)
  5  select count(*) from (
  6  select a.x||'+'||b.x||'-'||c.x||'==0' from a a,t b,t c
  7  where a.x+b.x-c.x=0 and a.x<494 and a.x<b.x and b.x<c.x
  8  and not exists(select 1 from (select rownum l from dual connect by level<=9)where instr(a.x||b.x||c.x ,l,1,2)>0))
  9  ;

  COUNT(*)
----------
       168

已用时间:  00: 00: 07.89

使用道具 举报

回复
论坛徽章:
32
祖国60周年纪念徽章
日期:2009-10-09 08:28:002013年新春福章
日期:2013-02-25 14:51:24迷宫蛋
日期:2013-06-28 11:09:23ITPUB季度 技术新星
日期:2013-07-30 16:04:58优秀写手
日期:2013-12-18 09:29:132014年新春福章
日期:2014-02-18 16:43:09马上有钱
日期:2014-02-18 16:43:09红孩儿
日期:2014-03-04 16:40:38美羊羊
日期:2015-02-16 16:36:28懒羊羊
日期:2015-03-04 14:52:11
56#
发表于 2010-6-11 11:52 | 只看该作者
老O还在研究啊,学习!

使用道具 举报

回复
论坛徽章:
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
57#
 楼主| 发表于 2010-6-11 18:52 | 只看该作者

建立索引,执行计划不变,终于运行出来了,居然无解


SQL> create index txidx on t(x);

索引已创建。

已用时间:  00: 00: 00.09
SQL> exec DBMS_STATS.GATHER_TABLE_STATS('LT','T');

PL/SQL 过程已成功完成。

已用时间:  00: 00: 00.25
SQL> explain plan for select count(*) from(
  2  select a.x||'+'||b.x||'='||to_char(to_number(a.x,'fmxxxx')+to_number(b.x,'fmxxxx'),'fmxxxx')s
  3  from t a,t b --,t c
  4  where to_number(a.x,'fmxxxx')<to_number('8000','fmxxxx')
  5        and to_number(a.x,'fmxxxx')<to_number(b.x,'fmxxxx')
  6        AND to_number(a.x,'fmxxxx')+to_number(b.x,'fmxxxx') <=to_number('fedc','fmxxxx')
  7        and translate('0123456789abcdef','$'||a.x||b.x||to_char(to_number(a.x,'fmxxxx')+to_number(b.x,'fmxxxx')),'$') is null
  8        );

已解释。

已用时间:  00: 00: 00.01
SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 4282957982

------------------------------------------------------------------------------
| Id  | Operation             | Name | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |      |     1 |    10 |    63  (31)| 00:00:01 |
|   1 |  SORT AGGREGATE       |      |     1 |    10 |            |          |
|   2 |   MERGE JOIN          |      | 11925 |   116K|    63  (31)| 00:00:01 |
|   3 |    SORT JOIN          |      |  2184 | 10920 |    24   (9)| 00:00:01 |
|*  4 |     TABLE ACCESS FULL | T    |  2184 | 10920 |    23   (5)| 00:00:01 |
|*  5 |    FILTER             |      |       |       |            |          |
|*  6 |     SORT JOIN         |      | 43680 |   213K|    24   (9)| 00:00:01 |
|   7 |      TABLE ACCESS FULL| T    | 43680 |   213K|    22   (0)| 00:00:01 |
------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - filter(TO_NUMBER("A"."X",'fmxxxx')<TO_NUMBER('8000','fmxxxx'))
   5 - filter(TO_NUMBER("A"."X",'fmxxxx')+TO_NUMBER("B"."X",'fmxxxx')<=T
              O_NUMBER('fedc','fmxxxx') AND TRANSLATE('0123456789abcdef','$'||"A"."X"|
              |"B"."X"||TO_CHAR(TO_NUMBER("A"."X",'fmxxxx')+TO_NUMBER("B"."X",'fmxxxx'
              )),'$') IS NULL)
   6 - access(TO_NUMBER("A"."X",'fmxxxx')<TO_NUMBER("B"."X",'fmxxxx'))
       filter(TO_NUMBER("A"."X",'fmxxxx')<TO_NUMBER("B"."X",'fmxxxx'))

已选择25行。

已用时间:  00: 00: 00.03
SQL> select count(*) from(
  2  select a.x||'+'||b.x||'='||to_char(to_number(a.x,'fmxxxx')+to_number(b.x,'fmxxxx'),'fmxxxx')s
  3  from t a,t b --,t c
  4  where to_number(a.x,'fmxxxx')<to_number('8000','fmxxxx')
  5        and to_number(a.x,'fmxxxx')<to_number(b.x,'fmxxxx')
  6        AND to_number(a.x,'fmxxxx')+to_number(b.x,'fmxxxx') <=to_number('fedc','fmxxxx')
  7        and translate('0123456789abcdef','$'||a.x||b.x||to_char(to_number(a.x,'fmxxxx')+to_number(b.x,'fmxxxx')),'$') is null
  8        );

  COUNT(*)
----------
         0

已用时间:  00: 43: 21.15
SQL>

使用道具 举报

回复
论坛徽章:
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
58#
发表于 2010-6-11 23:44 | 只看该作者
你建的临时表T为什么用LEVEL=4的?不是应该有五位吗?
你还必须把TO_NUMBER另外建一个列,后面省很多计算。
我的WITH写法跑了一个多小时出不来,被我停掉了。

使用道具 举报

回复
论坛徽章:
26
2010年世界杯参赛球队:阿根廷
日期:2010-07-15 16:49:17马上加薪
日期:2014-10-30 09:48:58马上有车
日期:2014-11-04 14:03:06马上有钱
日期:2015-01-13 10:14:512015年新春福章
日期:2015-03-04 14:51:122015年新春福章
日期:2015-03-06 11:57:31喜羊羊
日期:2015-03-16 10:05:36慢羊羊
日期:2015-06-02 11:57:03慢羊羊
日期:2015-06-17 16:43:46巨蟹座
日期:2015-10-19 10:12:48
59#
发表于 2010-6-11 23:46 | 只看该作者
无解的原因是条件translate('0123456789abcdef','$'||a.x||b.x||to_char(to_number(a.x,'fmxxxx')+to_number(b.x,'fmxxxx')),'$') is null 的问题.

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
60#
 楼主| 发表于 2010-6-12 07:49 | 只看该作者
select count(*) from(
select a.x||'+'||b.x||'='||to_char(to_number(a.x,'fm0xxx')+to_number(b.x,'fm0xxx'),'fm0xxx')s
from t a,t b --,t c
where to_number(a.x,'fm0xxx')<to_number('8000','fm0xxx')
      and to_number(a.x,'fm0xxx')<to_number(b.x,'fm0xxx')
      AND to_number(a.x,'fm0xxx')+to_number(b.x,'fm0xxx') <=to_number('fedc','fm0xxx')
      and length(translate('0123456789abcdef','$'||a.x||b.x||to_char(to_number(a.x,'fm0xxx')+to_number(b.x,'fm0xxx')),'$'))=4
      );

使用道具 举报

回复

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

本版积分规则 发表回复

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