ITPub博客

首页 > 数据库 > Oracle > [20220124]开发不应该这样写sql3.txt

[20220124]开发不应该这样写sql3.txt

原创 Oracle 作者:lfree 时间:2022-01-24 10:49:42 0 删除 编辑

[20220124]开发不应该这样写sql3.txt

--//在sql优化中,遇到sql语句出现这样的写法:
select
...
(case
                 when basyxx.icu_start is not null then
                  to_date(replace(replace(replace(replace(replace(replace(icu_start,
                                                                          '年',
                                                                          '-'),
                                                                  '月',
                                                                  '-'),
                                                          '日',
                                                          ' '),
                                                  '时',
                                                  ':'),
                                          '分',
                                          ''),
                                  '  ',
                                  ' '),
                          'yyyy-mm-dd hh24:mi')
                 else
                  null
               end) as scs_cutd_inpool_time,
...
from ...;

--//很明显开发想把一个日期格式的字符串转化为日期类型.使用6个replace.我尝试写的更加简洁一些.

1.环境:
SCOTT@78> @ ver1
PORT_STRING                    VERSION        BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx            11.2.0.4.0     Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

2.测试:
SCOTT@78> select to_date('2022年01月24日08时01分23秒','YYYY年MM月DD日HH24时MI分SS秒') from dual;
select to_date('2022年01月24日08时01分23秒','YYYY年MM月DD日HH24时MI分SS秒') from dual
                                            *
ERROR at line 1:
ORA-01821: date format not recognized

--//不识别这样的方式.

SCOTT@78> select translate('2022年01月24日08时01分23秒','年月日时分秒' ,'---::') c20 from dual ;
C20
--------------------
2022-01-24-08:01:23
--//日 应该转换为' '.

SCOTT@78> select to_date(translate('2022年1月24日08时1分23秒','年月日时分秒' ,'---::'),'yyyy-mm-dd hh24:mi:ss') c20 from dual ;
C20
--------------------
2022-01-24 08:01:23
--//不过转换没有问题.这样讲我这样写更加灵活.

SCOTT@78> select to_date(translate('2022年1月09日08时1分23秒','年月日时分秒' ,'---::'),'yyyy-mm-dd hh24:mi:ss') c20 from dual ;
C20
--------------------
2022-01-09 08:01:23

SCOTT@78> select to_date(translate('2012年06月22日 12时','年月日时分秒' ,'---::'),'yyyy-mm-dd hh24:mi') c20 from dual ;
C20
--------------------
2012-06-22 12:00:00

--//这样写我仅仅使用两个函数.至于效率如何简单测试看看.
create table t1 as select '2022年1月24日08时1分' v1 from dual connect by level<1e6;

SCOTT@78> create table t1 as select '2022年1月24日08时1分' v1 from dual connect by level<1e6;
Table created.

$ cat aa.txt
set timing on
select sysdate from dual;
set term off
select to_date(translate(v1,'年月日时分' ,'-- : '),'yyyy-mm-dd hh24:mi:ss') c20 from t1 ;
--select to_date(replace(replace(replace(replace(replace(replace(v1,
--                                                                          '年',
--                                                                          '-'),
--                                                                  '月',
--                                                                  '-'),
--                                                          '日',
--                                                          ' '),
--                                                  '时',
--                                                  ':'),
--                                          '分',
--                                          ''),
--                                  '  ',
--                                  ' '),
--                          'yyyy-mm-dd hh24:mi') from t1;
set term on
select sysdate from dual;


SCOTT@78> @ aa.txt
SYSDATE
-------------------
2022-01-24 09:28:20
Elapsed: 00:00:00.01
SYSDATE
-------------------
2022-01-24 09:28:37
Elapsed: 00:00:00.01

--//17秒.

SCOTT@78> @ aa.txt
SYSDATE
-------------------
2022-01-24 09:30:14

Elapsed: 00:00:00.02
SYSDATE
-------------------
2022-01-24 09:30:30
Elapsed: 00:00:00.01

--//16秒.视乎使用replace更快一些,不过从简洁性讲使用translate更好看一些.
--//取消后面的:ss,修改如下测试:
select to_date(translate(v1,'年月日时分' ,'-- : '),'yyyy-mm-dd hh24:mi') c20 from t1 ;
--//测试结果16秒.换一个方式测试:

SCOTT@78> @ tpt/sl all
alter session set statistics_level = all;
Session altered.

SCOTT@78> set timing on
SCOTT@78> with a as (select /*+ MATERIALIZE */ to_date(translate(v1,'年月日时分' ,'-- : '),'yyyy-mm-dd hh24:mi') c20 from t1) select count(distinct c20) from a;
COUNT(DISTINCTC20)
------------------
                 1

Elapsed: 00:00:03.47

SCOTT@78> with a as (select /*+ MATERIALIZE */ to_date(replace(replace(replace(replace(replace(replace(v1,'年', '-'), '月', '-'), '日', ' '), '时', ':'), '分', ''), '  ', ' '), 'yyyy-mm-dd hh24:mi') c20 from t1)
  2  select count(distinct c20 ) from a ;
COUNT(DISTINCTC20)
------------------
                 1

Elapsed: 00:00:03.55

--//视乎这样不使用函数,这样测试不行.
--//在toad下测试,视乎两者差别不大.

SCOTT@78> select to_date(translate(v1,'年月日时分' ,'-- : '),'yyyy-mm-dd hh24:mi') c20 from t1 group by to_date(translate(v1,'年月日时分' ,'-- : '),'yyyy-mm-dd hh24:mi');
C20
--------------------
2022-01-24 08:01:00
Elapsed: 00:00:02.33

SCOTT@78> @ dpc '' 'outline projection' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  fz9796dx1vajq, child number 0
-------------------------------------
select to_date(translate(v1,'年月日时分' ,'-- : '),'yyyy-mm-dd hh24:mi') c20
from t1 group by to_date(translate(v1,'年月日时分' ,'-- : '),'yyyy-mm-dd
hh24:mi')
Plan hash value: 136660032
------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |      1 |        |       |  1024 (100)|          |      1 |00:00:02.33 |    3604 |       |       |          |
|   1 |  HASH GROUP BY     |      |      1 |      1 |    21 |  1024   (3)| 00:00:13 |      1 |00:00:02.33 |    3604 |    48M|  9689K|  929K (0)|
|   2 |   TABLE ACCESS FULL| T1   |      1 |    999K|    20M|   999   (1)| 00:00:12 |    999K|00:00:00.10 |    3604 |       |       |          |
------------------------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1
   2 - SEL$1 / T1@SEL$1
Outline Data
-------------
  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.4')
      DB_VERSION('11.2.0.4')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      FULL(@"SEL$1" "T1"@"SEL$1")
      USE_HASH_AGGREGATION(@"SEL$1")
      END_OUTLINE_DATA
  */
Column Projection Information (identified by operation id):
-----------------------------------------------------------
   1 - TO_DATE(TRANSLATE("V1",'年月日时分','-- : '),'yyyy-mm-dd hh24:mi')[8]
   2 - "V1"[CHARACTER,20]

SCOTT@78> select to_date(replace(replace(replace(replace(replace(replace(v1,'年', '-'), '月', '-'), '日', ' '), '时', ':'), '分', ''), '  ', ' '), 'yyyy-mm-dd hh24:mi') c20 from t1
          group by to_date(replace(replace(replace(replace(replace(replace(v1,'年', '-'), '月', '-'), '日', ' '), '时', ':'), '分', ''), '  ', ' '), 'yyyy-mm-dd hh24:mi') ;
C20
--------------------
2022-01-24 08:01:00
Elapsed: 00:00:02.45

--//可以看出确实差别不大,好像使用translate更快一些.
SCOTT@78> select to_date(translate(v1,'年月日时分秒' ,'-- :: '),'yyyy-mm-dd hh24:mi:ss') c20 from t1 group by to_date(translate(v1,'年月日时分秒' ,'-- :: '),'yyyy-mm-dd hh24:mi:ss');
C20
--------------------
2022-01-24 08:01:00
Elapsed: 00:00:03.16

--//你可以看出如果我加入多了秒的替换,执行时间增加不少.

3.总结:
我开始测试加入秒的转换,测试使用translate确实慢一点点,没有注意这个细节,取消后两者基本一致.很明显我使用translate更加清晰明了.
我总觉觉得许多开发认为逻辑正确就ok了,丢失许多基本的算法与基础知识的东西.

SCOTT@78> select v1 c20 from t1 group by v1;
C20
--------------------
2022年1月24日08时1分
Elapsed: 00:00:00.32

--//仔细看可以发现原始语句多比我做了1次replace.视乎replace更快一些.


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/267265/viewspace-2853749/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
熟悉oracle相关技术,擅长sql优化,rman备份与恢复,熟悉linux shell编程。

注册时间:2008-01-03

  • 博文量
    4006
  • 访问量
    7969669