Oracle INCREMENT 时间戳的小数部分
Oracle INCREMENT fractional parts of a timestamp
我有一个 table,其中包含一个时间戳。我希望每行间隔一个 INTERVAL。在下面的示例中,我使用了 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.') 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
…
…
看来您只想添加一个 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 显示它生成了您想要的输出。
您可以使用:
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<>fiddle here
我有一个 table,其中包含一个时间戳。我希望每行间隔一个 INTERVAL。在下面的示例中,我使用了 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.') 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
…
…
看来您只想添加一个 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 显示它生成了您想要的输出。
您可以使用:
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<>fiddle here