将两个日期时间转换为时间戳并保留较大的一个

Convert two datetimes to timestamps and keep the larger one

我使用 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
)

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

使用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<>fiddle here

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