我正在使用Oracle SQL。我正在尝试使用sysdate和时间来查询查询结果。我在where子句中放置了一个时间,但是我需要它是自动的,并且使用sysdate并将其转换为本地时间是正确的方法。有什么想法吗?
SELECT RESOURCE, AVG(SALES) AS SALES
FROM Z_HOURLY_RESOURCE
WHERE DATE_TIME_START BETWEEN to_date(to_char(FROM_TZ( CAST( (to_date('2018-08-02T05:00:00','yyyy-MM-dd"T"HH24:mi:ss') )AS TIMESTAMP ), 'America/Los_Angeles') AT TIME ZONE 'UTC', 'yyyy-MM-dd"T"HH24:mi:ss'),'yyyy-MM-dd"T"HH24:mi:ss')
AND to_date(to_char(FROM_TZ( CAST( (to_date('2018-08-02T13:00:00','yyyy-MM-dd"T"HH24:mi:ss')+1) AS TIMESTAMP ), 'America/Los_Angeles') AT TIME ZONE 'UTC', 'yyyy-MM-dd"T"HH24:mi:ss'),'yyyy-MM-dd"T"HH24:mi:ss')
答案 0 :(得分:3)
在没有样本数据的情况下很难满足您的需求,但是听起来您想将本地会话时区(例如LA)中的05:00到13:00的时间范围转换为UTC以便与表中基于UTC的时间戳。
您可以执行以下操作:
WHERE DATE_TIME_START >= sys_extract_utc(cast(trunc(current_date) + 5/24 as timestamp with time zone))
AND DATE_TIME_START < sys_extract_utc(cast(trunc(current_date) + 13/24 as timestamp with time zone))
在您确实希望最多 13:00的假设下,我使用了>=
和<
而不是between
,通常情况是时间范围。如果您确实希望完全按照13:00:00的格式包含数据,则将<
更改为<=
,或返回到between
。
解释正在执行的操作,但是:current_date
为您提供会话时区中的日期/时间。截断会将时间设置为午夜(默认情况下),因此您可以添加5或13个小时来获取所需的时间。那仍然是一个日期,因此您可以将其强制转换为带有时区的时间戳,以便它再次代表您的会话时区中的时间。然后,您可以使用sys_extract_utc()
来获取与UTC等效的时间戳。
演示这些步骤:
alter session set time_zone = 'America/Los_Angeles';
alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS';
alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS.FF1';
alter session set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS.FF1 TZH:TZM';
select sysdate as a,
current_date as b,
trunc(current_date) as c,
trunc(current_date) + 5/24 as d,
cast(trunc(current_date) + 5/24 as timestamp with time zone) as e,
sys_extract_utc(cast(trunc(current_date) + 5/24 as timestamp with time zone)) as f
from dual
union all
select sysdate as a,
current_date as b,
trunc(current_date) as c,
trunc(current_date) + 13/24 as d,
cast(trunc(current_date) + 13/24 as timestamp with time zone) as e,
sys_extract_utc(cast(trunc(current_date) + 13/24 as timestamp with time zone)) as f
from dual;
A B C D E F
------------------- ------------------- ------------------- ------------------- ---------------------------- ---------------------
2018-08-02 18:56:23 2018-08-02 10:56:23 2018-08-02 00:00:00 2018-08-02 05:00:00 2018-08-02 05:00:00.0 -07:00 2018-08-02 12:00:00.0
2018-08-02 18:56:23 2018-08-02 10:56:23 2018-08-02 00:00:00 2018-08-02 13:00:00 2018-08-02 13:00:00.0 -07:00 2018-08-02 20:00:00.0
答案 1 :(得分:1)
首先,您不必将TIMESTAMP
强制转换为CHAR
,然后再次转换为TIMESTAMP
。
假设DATE_TIME_START
是TIMESTAMP
,并且时间以UTC给出,则可以使其更简单。当Oracle比较TIMESTAMP WITH TIME ZONE
值时,比较总是在UTC时间值自动进行。您的情况就是这样。
SELECT RESOURCE, AVG(SALES) AS SALES
FROM Z_HOURLY_RESOURCE
WHERE FROM_TZ(DATE_TIME_START, 'UTC')
BETWEEN TO_TIMESTAMP_TZ('2018-08-02T05:00:00 America/Los_Angeles', 'yyyy-MM-dd"T"HH24:mi:ss TZR')
AND TO_TIMESTAMP_TZ('2018-08-02T13:00:00 America/Los_Angeles', 'yyyy-MM-dd"T"HH24:mi:ss TZR')
但是,由于功能FROM_TZ(DATE_TIME_START, 'UTC')
,性能可能不是最佳的,这取决于您的数据。
如果您需要基于当前时间的条件,它将是这样的:
SELECT RESOURCE, AVG(SALES) AS SALES
FROM Z_HOURLY_RESOURCE
WHERE FROM_TZ(DATE_TIME_START, 'UTC')
BETWEEN TRUNC(SYSTIMESTAMP)
AND TRUNC(SYSTIMESTAMP) + INTERVAL '1' DAY
以上查询仅说明了时区处理。您不必考虑时区SYSTIMESTAMP
,在任何情况下都可以进行比较。