【问题标题】:Convert two datetimes to timestamps and keep the larger one将两个日期时间转换为时间戳并保留较大的一个
【发布时间】:2021-10-31 15:50:27
【问题描述】:

我使用 Oracle Database 19c,我想将两个日期时间 (DD/MM/YY HH24:MM:SS) 转换为时间戳,只保留较大的一个。

我尝试了几个这样的转换脚本:

SELECT 
CODE_ACT_PROD, 
LIB, 
CAST (DAT_CRE AS TIMESTAMP) AS DATE_CRE_TIMESTAMP,
CAST (DAT_MOD AS TIMESTAMP) AS DATE_MOD_TIMESTAMP
FROM ACTI
WHERE CODE_ACT_PROD
IN (
    SELECT CODE_ACT_PROD
    FROM ART_COM
    WHERE ETAT = 0
)

但结果不是我想要的,日期时间没有转换,我不知道如何保留较大的。

【问题讨论】:

    标签: oracle19c


    【解决方案1】:

    使用GREATEST:

    SELECT CODE_ACT_PROD, 
           LIB, 
           CAST (DAT_CRE AS TIMESTAMP) AS DATE_CRE_TIMESTAMP,
           CAST (DAT_MOD AS TIMESTAMP) AS DATE_MOD_TIMESTAMP,
           CAST(GREATEST(DAT_CRE, DAT_MOD) AS TIMESTAMP) AS greatest_timestamp
    FROM   ACTI
    WHERE  CODE_ACT_PROD IN (
             SELECT CODE_ACT_PROD
             FROM   ART_COM
             WHERE  ETAT = 0
           )
    

    其中,对于样本数据:

    CREATE TABLE acti (
      code_act_prod INT,
      lib           INT,
      dat_cre       DATE,
      dat_mod       DATE
    );
    
    CREATE TABLE art_com (
      code_act_prod INT,
      etat          INT
    );
    
    INSERT INTO acti (code_act_prod, lib, dat_cre, dat_mod)
    SELECT 1, 2, SYSDATE - 1, SYSDATE FROM DUAL UNION ALL
    SELECT 3, 4, TRUNC(SYSDATE), SYSDATE - 2 FROM DUAL;
    
    INSERT INTO art_com (code_act_prod, etat)
    SELECT 1, 0 FROM DUAL UNION ALL
    SELECT 3, 0 FROM DUAL;
    

    输出:

    CODE_ACT_PROD LIB DATE_CRE_TIMESTAMP DATE_MOD_TIMESTAMP GREATEST_TIMESTAMP
    1 2 2021-09-01 08:38:21.000000 2021-09-02 08:38:21.000000 2021-09-02 08:38:21.000000
    3 4 2021-09-02 00:00:00.000000 2021-08-31 08:38:21.000000 2021-09-02 00:00:00.000000

    db小提琴here

    【讨论】:

      【解决方案2】:

      Oracle 没有datetime 数据类型。它有date,它有一天和一秒的时间。它有一个timestamp,它也有一天和秒的时间,可选的小数秒和时区。将date 转换为timestamp 只会添加始终为0 的小数秒。datetimestamp 数据类型都没有格式。 varchar2 将具有格式。如果列是 date 数据类型,则您的代码在语法上是有效的。我不确定你得到的结果与你想要的结果有什么不同,因为你没有向我们展示你的样本数据或预期的结果,当你说某些东西没有被转换时,你也没有告诉我们你的意思。

      假设这两列实际上是date 类型,您的代码似乎没问题,您只想使用greatest 函数来获取最新日期。见this fiddle

      with cte as (
        select sysdate dat_cr, sysdate + 1 dat_mod
          from dual
      )
      select cast(dat_cr as timestamp) ts_cr,
             cast(dat_mod as timestamp) ts_mod,
             cast( greatest( dat_cr, dat_mod ) as timestamp ) ts_greatest
        from cte;
      
      TS_CR                           TS_MOD                          TS_GREATEST
      02-SEP-21 08.25.38.000000 AM    03-SEP-21 08.25.38.000000 AM    03-SEP-21 08.25.38.000000 AM
      

      请注意,将三个时间戳转换为要显示给人类的字符串是由会话的nls_timestamp_format 控制的。

      如果您想通过返回 not null 中的任何一个日期来处理 null 日期,您可以使用 coalescecase 语句

      with cte as (
        select sysdate dat_cr, sysdate + 1 dat_mod
          from dual
        union all
        select null, sysdate from dual
        union all
        select sysdate, null from dual
      )
      select cast(dat_cr as timestamp) ts_cr,
             cast(dat_mod as timestamp) ts_mod,
             cast( case when dat_cr is null or dat_mod is null
                        then coalesce( dat_mod, dat_cr )
                        else greatest( dat_cr, dat_mod ) 
                     end
                    as timestamp ) ts_greatest
        from cte;
      

      this fiddle

      【讨论】:

      • 好的,谢谢@mt0 它可以工作,但是如果 DAT_MOD 为空,则返回空...如果 DAT_MOD 为空,有没有办法返回 DAT_CRE?
      • @paskaloverpo - 更新了我的答案。
      猜你喜欢
      • 2020-07-06
      • 1970-01-01
      • 1970-01-01
      • 2017-04-25
      • 2022-01-08
      • 1970-01-01
      相关资源
      最近更新 更多