从提取错误的小时提取(小时...)

时间:2017-06-19 17:54:48

标签: sql oracle11g timestamp

我尝试根据同一小时创建的行数进行报告,并且我尝试使用提取功能对行进行分组,但它会更改结果信息,因为例如:

 select 
 to_char(resolved_time,'YY/MM/DD') Day,
 to_char(resolved_time, 'HH24') hour_tmp,
 extract(hour from resolved_time) Hour
 from RESOLUTION_HISTORY h
 where resolved_time >= timestamp '2017-01-01 00:00:00'
 and resolved_time < timestamp '2017-01-02 00:00:00'
 and modified_by in 'user1'
 order by 2;

我的结果看起来像这样:

Day         Hour_Tmp    Hour
17/01/01    14          20
17/01/01    14          20
17/01/01    14          20
17/01/01    14          20
17/01/01    14          20
17/01/01    14          20
17/01/01    14          20
17/01/01    14          20
17/01/01    15          21
17/01/01    17          23
17/01/01    17          23
17/01/01    18          0

正如你所看到的,解析时间和提取的实际值之间存在差异,试图改变我的会话但它似乎没有帮助。 是否还有其他选项可以在本地会话中更改此设置?

1 个答案:

答案 0 :(得分:2)

您看到的差异是UTC与您的列值相关的时区之间的偏差。您可以看到简化版本:

select extract(hour from timestamp '2017-01-01 00:00:00 America/New_York') from dual;

EXTRACT(HOURFROMTIMESTAMP'2017-01-0100:00:00AMERICA/NEW_YORK')
--------------------------------------------------------------
                                                             5

DBTIMEZONE按照建议使用+00:00,数据库服务器在BST上,我的会话也是BST(通过欧洲/伦敦)。但这些都不相关。

Buried in the documentation

  

从具有时区值的日期时间中提取时,返回的值为UTC。

(如果您的专栏为timestamp with local time zone,您会在会话时区看到小时,这可能更不实用。)

您可以通过将列转换为纯时间戳来解决此问题,这实际上会截断时区信息:

extract(hour from cast(resolved_time as timestamp))

使用您的数据,您可以看到与以下内容的区别:

select 
 to_char(resolved_time,'YYYY-MM-DD HH24:MI:SS TZR') full_value,
 to_char(resolved_time,'YY/MM/DD') Day,
 to_char(resolved_time, 'HH24') hour_tmp,
 extract(hour from resolved_time) Hour_utc,
 extract(hour from cast(resolved_time as timestamp)) Hour
 from RESOLUTION_HISTORY h
 where resolved_time >= timestamp '2017-01-01 00:00:00 America/New_York'
 and resolved_time < timestamp '2017-01-02 00:00:00 America/New_York'
 and modified_by in 'user1'
 order by 2;

FULL_VALUE                                           DAY      HO   HOUR_UTC       HOUR
---------------------------------------------------- -------- -- ---------- ----------
2017-01-01 12:00:00 AMERICA/NEW_YORK                 17/01/01 12         17         12

顺便提一下,我在过滤条件中包含了(假设的)列时区值,因此它不必依赖于您的会话时区。如果您有来自多个时区的值,那么您也需要在过滤器中允许这样做,并且可能需要在提取和分组之前将列值转换为特定区域。取决于你想要做的事情。

另见Tony’s Tirade against TIMESTAMP WITH TIME ZONE