将毫秒移动一个位置值

Move milliseconds by one position value

由于 "incorrect" java parsing date(我的错)我现在在 oracle DB 中有几千个时间戳不正确的条目。 问题如下:

2018-06-26 11:15:43.950 的时间戳已作为 26-FEB-18 11.15.43.095000000 上午

有没有缩小毫秒的功能?我只是想通了一些 to_char , to_date 函数结合子字符串我可以 "remove" 0 在毫秒前面,但在我看来分辨率不够好。

提前致谢!

编辑:不幸的是,我无法使用更正的算法重新上传数据。

您可以使用 TRUNC( time, 'MI' ) 获取没有秒部分的时间(作为日期数据类型,然后您可以使用 CAST 将其转换回时间戳)。然后,您可以使用 EXTRACT( SECOND from time ) 获取秒(包括小数秒)组件并将其拆分为秒和毫秒组件(后者只需乘以 10 即可执行校正),然后使用 NUMTODSINTERVAL将数值转换为可以添加到截断时间戳的间隔。

像这样:

SQL Fiddle

Oracle 11g R2 架构设置:

CREATE TABLE times ( time ) AS
SELECT TIMESTAMP '2018-06-26 11:15:43.095' FROM DUAL;

查询 1:

SELECT time,
       CAST( TRUNC( time, 'MI' ) AS TIMESTAMP )
       + NUMTODSINTERVAL(
           TRUNC( EXTRACT( SECOND FROM time ) )
           + MOD( EXTRACT( SECOND FROM time ), 1 ) * 10,
           'SECOND'
         ) As updated_time
FROM   times

Results:

|                    TIME |           UPDATED_TIME |
|-------------------------|------------------------|
| 2018-06-26 11:15:43.095 | 2018-06-26 11:15:43.95 |

但是,您最好使用更正的算法再次(如果可以)从您的源数据上传时间戳,因为您将丢失毫秒中的 least-significant 数字。

很遗憾,您的数据永远损坏了。无法区分移动时间戳和正确时间戳:

2018-06-26 11:15:43.950 
2018-06-26 11:15:43.095 

两者都会产生以下时间戳

26-FEB-18 11.15.43.095000000 AM

最佳选择:修复代码后从原始来源重新加载数据。

如果您无法再访问原始数据,并且必须就地修复所有数据,请使用下面的 UPDATE 语句(如上下文所示):

create table tbl ( ts timestamp );

insert into tbl ( ts ) values ( timestamp '2018-06-26 11:15:43.0950' );
commit;

select ts from tbl;

TS                                     
----------------------------------------
2018-06-26 11.15.43.095000000         

update tbl set ts = ts + 9 * (ts - cast(ts as timestamp(0)));

1 row updated.

commit;

select ts from tbl;

TS                                     
----------------------------------------

2018-06-26 11.15.43.950000000  

解释:

如果您的原始时间戳的格式为 X + w,其中 X 是整数秒,w 是小数秒部分,则当前值为 X + z,其中 z = w/10。 (您在小数点后添加了一个错误的 0,这意味着您将 w 除以十)。所以:你目前有 X + z,但你想要 X + w,或者换句话说,X + 10 * z。因此,您必须将 9 * z 添加到您已有的内容中。

要获得 z(时间戳的小数部分),您需要从时间戳中减去 X(整数部分)。 X 本身就是将时间戳截断为整秒。没有 TRUNC() 函数可以截断整秒,但是 CASTTIMESTAMP(0) 的函数可以很好地完成这项工作。

要使用您的示例数据:X 是时间戳 '2018-06-26 11:15:43.000000'。这也是cast(ts as timestamp(0))的结果。 w.9500,而 z 是使它成为您的 table、.0950 的原因。您当前的值为 X + z,但您想要 X + w。那就是 X + 10 * z = (X + z) + 9 * z,现在记住 (X + z) 只是 ts(你目前在 table 中的值)所以你只需要加上九倍的值 z,也就是差值(ts - X).