【问题标题】:Extract(hour from ...) wrong hour extractedExtract(hour from ...) 提取错误的时间
【发布时间】:2017-06-19 17:54:47
【问题描述】:

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

 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

如您所见,解决时间的实际值与提取之间存在差异,试图改变我的会话,但似乎没有帮助。 是否有任何其他选项可以在本地会话中更改此设置?

【问题讨论】:

  • 您能否确认列数据类型为timestamp with time zone(不是普通时间戳)、您查询的值的时区以及执行查询时的会话时区?你的数据库时区呢?
  • 是的,它是带时区的时间戳

标签: sql oracle11g timestamp


【解决方案1】:

您看到的差异是 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

【讨论】:

  • 谢谢! extract(hour from cast(resolved_time as timestamp)) 小时成功了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多