我有一个timestamp列,其中包含具有不同时区的数据。我需要选择属于给定数据库服务器时区“天”的记录。
例如,如果MY_TIMESTAMP
列中的数据为19-MAR-19 00.37.56.030000000 EUROPE/PARIS
。
并且在给定日期19-MAR-19
(也表示为2019078)中,数据库服务器位于EUROPE/LONDON
上。
有什么方法可以使如果我的数据库服务器处于EUROPE/LONDON
时区,那么该记录将被忽略,但是如果它处于EUROPE/PARIS
,则将选择该记录。
请注意,给定的时间戳记是一天中的第一个小时,EUROPE/PARIS
比EUROPE/LONDON
早一小时
不幸的是,我尝试的查询忽略了时间戳的时区。
select *
from MY_TABLE
where
to_number(to_char(CAST(MY_TIMESTAMP AS DATE), 'RRRRDDD')) between 2019078 AND 2019079
下面介绍了将TIMESTAMP从已知时区转换为所需时区中的日期的方法,但是由于源时区未知,我无法使用此逻辑。
CAST((FROM_TZ(CAST(MY_TIMESTAMP AS TIMESTAMP),'EUROPE/PARIS') AT TIME ZONE 'EUROPE/LONDON') AS DATE)
'
答案 0 :(得分:3)
您不需要转换表数据;以及增加工作量,这样做会停止使用该列上的任何索引。
Oracle在比较值时会遵守时区,因此将原始表数据与特定日期进行比较-并将其转换为具有时区的时间戳:
select *
from MY_TABLE
where MY_TIMESTAMP >= timestamp '2019-03-19 00:00:00 Europe/London'
and MY_TIMESTAMP < timestamp '2019-03-20 00:00:00 Europe/London'
,或者如果要基于今天而不是固定日期:
where MY_TIMESTAMP >= from_tz(cast(trunc(sysdate) as timestamp), 'Europe/London')
and MY_TIMESTAMP < from_tz(cast(trunc(sysdate) + 1 as timestamp), 'Europe/London')
或者如果将日期传递为YYYYDDD值(用数字参数名称替换固定值):
where MY_TIMESTAMP >= from_tz(to_timestamp(to_char(2019078), 'RRRRDDD'), 'Europe/London')
and MY_TIMESTAMP < from_tz(to_timestamp(to_char(2019079), 'RRRRDDD'), 'Europe/London')
在CTE中以一些示例数据进行快速演示,为简单起见,在两个区域中进行了演示:
with my_table (id, my_timestamp) as (
select 1, timestamp '2019-03-19 00:37:56.030000000 Europe/Paris' from dual
union all
select 2, timestamp '2019-03-19 00:37:56.030000000 Europe/London' from dual
union all
select 3, timestamp '2019-03-19 01:00:00.000000000 Europe/Paris' from dual
union all
select 4, timestamp '2019-03-20 00:37:56.030000000 Europe/Paris' from dual
union all
select 5, timestamp '2019-03-20 00:37:56.030000000 Europe/London' from dual
)
select *
from MY_TABLE
where MY_TIMESTAMP >= timestamp '2019-03-19 00:00:00 Europe/London'
and MY_TIMESTAMP < timestamp '2019-03-20 00:00:00 Europe/London'
/
ID MY_TIMESTAMP
---------- --------------------------------------------------
2 2019-03-19 00:37:56.030000000 EUROPE/LONDON
3 2019-03-19 01:00:00.000000000 EUROPE/PARIS
4 2019-03-20 00:37:56.030000000 EUROPE/PARIS
排除第一行示例,因为巴黎的00:37仍然是伦敦的前一天。之所以包括第二排和第三排,是因为它们都是在当天的凌晨-第三排才刚刚出现。出于同样的原因,也包括了第四排,因为第一排被排除在外-明天00:37今天仍然是伦敦。并且排除了第五个,因为它是在伦敦的午夜之后。