将两个日期时间转换为时间戳并保留较大的一个
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 的小数秒。date
和 timestamp
数据类型都没有格式。 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
日期,您可以使用 coalesce
和 case
语句
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;
我使用 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 的小数秒。date
和 timestamp
数据类型都没有格式。 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
日期,您可以使用 coalesce
和 case
语句
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;