sql >> データベース >  >> RDS >> Oracle

OracleSQLの日付をLongに、またはその逆。

    変換の精度が低下しすぎて、他の方法に戻ることができません。日付の代わりにタイムスタンプを使用することで、より近づくことができます。

    まず、最初のクエリで時間コンポーネントが完全に失われていました:

    select to_char(date '1970-01-01'
      + (1432550197431912935 - power(2, 60))/power(2, 44), 'YYYY-MM-DD HH24:MI:SS')
    from dual;
    
    2013-07-09 01:13:19
    

    ...しかし、それでも、元に戻すことはあまりにも道に迷っています:

    select ((to_date('2013-07-09 01:13:19','YYYY-MM-DD HH24:MI:SS')
      - date '1970-01-01') * power(2, 44)) + power(2, 60) from dual;
    
    1432550197477589405
    

    これは、入手した1432549301782839296よりも近いですが、それでもかなり遠いです。

    問題の一部は、DATEの精度です。 、これは秒単位です。 TIMESTAMPを使用する場合 代わりに、かなり近づくことができます。持つべき価値はおそらく非常に正確であることがわかります:

    select timestamp '1970-01-01 00:00:00'
      + numtodsinterval((1432550197431912935 - power(2, 60))/power(2, 44), 'DAY')
    from dual;
    
    2013-07-09 01:13:18.775670462
    

    タイムスタンプ演算によって間隔の結果が得られるため、その変換は複雑になります。間隔の結果を操作して、最初は元の日数として数値に戻す必要があります。

    select extract(day from int_val)
      + extract(hour from int_val) / 24
      + extract(minute from int_val) / (24 * 60)
      + extract(second from int_val) / (24 * 60 * 60)
    from (
    select to_timestamp('2013-07-09 01.13.18.775670462', 'YYYY-MM-DD HH24:MI:SS.FF9')
      - timestamp '1970-01-01 00:00:00' as int_val from dual);
    
    15895.0509117554451620370370370370370371
    

    ...そしてあなたの力の操作で:

    select ((extract(day from int_val)
        + extract(hour from int_val) / 24
        + extract(minute from int_val) / (24 * 60)
        + extract(second from int_val) / (24 * 60 * 60))
      * power(2, 44)) + power(2, 60)
    as x
    from (
    select to_timestamp('2013-07-09 01.13.18.775670462', 'YYYY-MM-DD HH24:MI:SS.FF9')
      - timestamp '1970-01-01 00:00:00' as int_val from dual);
    
    1432550197431912935.09988554676148148148
    

    これはかなり近いです。これを切り捨てるか、最も近い整数に丸めることができます。

    数値と電力操作をそれぞれの方法で見るだけで、Oracleが対処できる精度の範囲内にあるように見えます。

    select (1432550197431912935 - power(2, 60)) / power(2, 44)
    from dual;
    
    15895.050911755445156359201064333319664
    
    select (15895.050911755445156359201064333319664 * power(2, 44)) + power(2, 60)
    from dual;
    
    1432550197431912935.000...
    

    タイムスタンプがあっても、その最初の値が9桁の小数の2番目の制限を超えているため、その一部が失われます。 15895時間などを考慮した後の秒の小数部を表す部分は、.0000089776673785814232865555418862です。 1日の.77567046150943497195839881896768 秒;タイムスタンプはそれを.775670462に丸めています 。したがって、完璧になることは決してありません。

    それはまた、元の番号がどのように生成されているのか疑問に思う人を導きます。 yoctoseconds 。 「精度」が実際に2の累乗に基づいて操作されたアーティファクトであるかどうかは明確ではありませんが、とにかくあまり有用ではないようです。数値として保存する必要がある場合は、使用しているエポック日付から数秒または場合によってはミリ秒をカウントして、Unixスタイルのエポック日付を使用するのがより一般的です。このデザインは...面白いです。



    1. mysqlでの正規表現キャプチャグループのシミュレーション

    2. Oracle11gでのJSONのサポート

    3. CentOS6.2でMySQLのバージョンを5.1から5.5に更新します

    4. プロバイダーは、Oracleクライアントのバージョンと互換性がありません