【问题标题】:Oracle INCREMENT fractional parts of a timestampOracle INCREMENT 时间戳的小数部分
【发布时间】:2022-01-18 08:04:04
【问题描述】:

我有一个表,其中包含一个时间戳。我希望每一行都有一个间隔。在下面的示例中,我使用的是 15 分钟间隔

我的第一个解决方案似乎运行良好,只是时间戳的小数部分始终为 .000000,这是我期望但不想要的。我希望它包含一些其他数字。

在我的第二次尝试中,我试图将时间戳的小数部分增加 .100000 这个解决方案的问题是,如果我在示例中创建了许多行 (1344),则时间戳的秒部分会增加插入 10 行后 1 秒。请参阅下面的第二个解决方案。我也不想要。

第三,我认为 regexp_replace 解决方案可能会起作用,我可以切断第二个解决方案的整数部分(保留小数部分),然后将其添加到我的区间。该尝试因错误而失败。请参阅下面的第三次尝试。

有没有办法让它工作?我可以在不影响日期的 MMDDYYYY HH24:MI:SS 部分的情况下更改时间戳的小数部分。

以下是我的代码和尝试以及我希望生成的示例输出示例。

尝试 #1 小数部分总是 .000000


CREATE TABLE t3 (
seq_num NUMBER  GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL,
dt TIMESTAMP  );
/

INSERT into t3 (dt)
with dt (dt, interv) as (
select timestamp '2022-01-01 00:00:00', 
numtodsinterval(15,'MINUTE') from dual
union all
select dt.dt + interv, interv from dt
where dt.dt + interv < date '2022-01-15')
select dt from dt;
/

SELECT * FROM T3 ORDER BY SEQ_NUM 

SEQ_NUM    DT
1    01-JAN-22 12.00.00.000000 AM
2    01-JAN-22 12.15.00.000000 AM
3    01-JAN-22 12.30.00.000000 AM
4    01-JAN-22 12.45.00.000000 AM
5    01-JAN-22 01.00.00.000000 AM
6    01-JAN-22 01.15.00.000000 AM
…
...
1342    14-JAN-22 11.15.00.000000 PM
1343    14-JAN-22 11.30.00.000000 PM
1344    14-JAN-22 11.45.00.000000 PM

尝试 #2 注意到 seq_num 1355 处的秒数变化。它从 :00 变为 :01


TRUNCATE TABLE T3;
/

INSERT into t3 (dt)
with dt (dt, interv) as (
select timestamp '2022-01-01 00:00:00', 
numtodsinterval(15,'MINUTE') +  
numtodsinterval(  (rownum * .100000), 'SECOND')  from dual
union all
select dt.dt + interv, interv from dt
where dt.dt + interv < date '2022-01-15')
select dt from dt;
/

SELECT * FROM T3 ORDER BY SEQ_NUM 

SEQ_NUM    DT
1345    01-JAN-22 12.00.00.000000 AM
1346    01-JAN-22 12.15.00.100000 AM
1347    01-JAN-22 12.30.00.200000 AM
1348    01-JAN-22 12.45.00.300000 AM
1349    01-JAN-22 01.00.00.400000 AM
1350    01-JAN-22 01.15.00.500000 AM
1351    01-JAN-22 01.30.00.600000 AM
1352    01-JAN-22 01.45.00.700000 AM
1353    01-JAN-22 02.00.00.800000 AM
1354    01-JAN-22 02.15.00.900000 AM
1355    01-JAN-22 02.30.01.000000 AM
1356    01-JAN-22 02.45.01.100000 AM
…
…

尝试 #3 失败


TRUNCATE TABLE T3;
/

INSERT into t3 (dt)
with dt (dt, interv) as (
select timestamp '2022-01-01 00:00:00', 
numtodsinterval(15,'MINUTE') +  
regexp_replace(
numtodsinterval(  (rownum * .100000), 'SECOND'), '[^.]+\.(.*)$', '0.\1') from dual
union all
select dt.dt + interv, interv from dt
where dt.dt + interv < date '2022-01-15')
select dt from dt;
/

ORA-30081: invalid data type for datetime/interval arith

期望的输出


SEQ_NUM    DT
1345    01-JAN-22 12.00.00.000000 AM
1346    01-JAN-22 12.15.00.100000 AM
1347    01-JAN-22 12.30.00.200000 AM
1348    01-JAN-22 12.45.00.300000 AM
1349    01-JAN-22 01.00.00.400000 AM
1350    01-JAN-22 01.15.00.500000 AM
1351    01-JAN-22 01.30.00.600000 AM
1352    01-JAN-22 01.45.00.700000 AM
1353    01-JAN-22 02.00.00.800000 AM
1354    01-JAN-22 02.15.00.900000 AM
1355    01-JAN-22 02.30.00.000000 AM
1356    01-JAN-22 02.45.00.100000 AM
1357    01-JAN-22 03.00.00.200000 AM
…
…

【问题讨论】:

    标签: oracle timestamp intervals


    【解决方案1】:

    你可以使用:

    INSERT into t3 (dt)
    SELECT TIMESTAMP '2022-01-01 00:00:00'
             + (LEVEL - 1) * INTERVAL '15' MINUTE
             + MOD(LEVEL - 1, 10) * INTERVAL '0.1' SECOND
    FROM   DUAL
    CONNECT BY
           TIMESTAMP '2022-01-01 00:00:00'
             + (LEVEL - 1) * INTERVAL '15' MINUTE
             + MOD(LEVEL - 1, 10) * INTERVAL '0.1' SECOND < DATE '2022-01-15';
    

    或:

    INSERT into t3 (dt)
    SELECT TIMESTAMP '2022-01-01 00:00:00'
            + NUMTODSINTERVAL((LEVEL-1)*15*60 + MOD(LEVEL-1, 10)/10, 'SECOND')
    FROM   DUAL
    CONNECT BY
          TIMESTAMP '2022-01-01 00:00:00'
            + NUMTODSINTERVAL((LEVEL-1)*15*60 + MOD(LEVEL-1, 10)/10, 'SECOND')
            < DATE '2022-01-15';
    

    两者都给出值:

    SEQ_NUM DT
    1 2022-01-01 00:00:00.000000
    2 2022-01-01 00:15:00.100000
    3 2022-01-01 00:30:00.200000
    4 2022-01-01 00:45:00.300000
    5 2022-01-01 01:00:00.400000
    6 2022-01-01 01:15:00.500000
    7 2022-01-01 01:30:00.600000
    8 2022-01-01 01:45:00.700000
    9 2022-01-01 02:00:00.800000
    10 2022-01-01 02:15:00.900000
    11 2022-01-01 02:30:00.000000

    db小提琴here

    【讨论】:

      【解决方案2】:

      看起来你只想添加 15 分 0.1 秒的间隔

      select level seq_num,
             timestamp '2022-01-01 00:00:00' + 
                (level-1) * interval '15' minute +
                (level-1) * interval '0.1' second dt
        from dual
      connect by level <= 10
      

      这里是a dbfiddle,它显示了它产生了你想要的输出。

      【讨论】:

      • 差不多。他们希望将毫秒从 0 旋转到 9,并且不会因此影响秒数。将(level-1) * interval '0.1' 更改为mod((level-1), 10) * interval '0.1' 以实现此目的。
      • ... 分秒当然不是毫秒 :-)
      • 感谢大家的回复。有没有办法在我不必调整 MOD 的值的情况下构建它。例如,假设我想要 .000025 的小数增量,我想要的是一个小数部分,它将在不增加秒数的情况下达到 .999975。我正在考虑 MTO 第一个解决方案,因为它包括停止时间,这正是我想要的。感谢您的帮助、专业知识和耐心
      猜你喜欢
      • 2020-07-13
      • 1970-01-01
      • 2020-09-28
      • 2011-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-28
      • 2011-10-04
      相关资源
      最近更新 更多