在雅典娜上转换为带时区的时间戳失败

Gal*_*hak 6 sql hive date timestamp-with-timezone amazon-athena

我正在尝试创建以下视图:

CREATE OR REPLACE VIEW view_events AS 
(
   SELECT
     "rank"() OVER (PARTITION BY "tb1"."innerid" ORDER BY "tb1"."date" ASC) "r"
   , "tb2"."opcode"
   , "tb1"."innerid"
   , "tb1"."date"
   , From_iso8601_timestamp(tb1.date) as "real_date"
   , "tb2"."eventtype"
   , "tb1"."fuelused"
   , "tb1"."mileage"
   , "tb1"."latitude"
   , "tb1"."longitude"
   FROM
     rt_message_header tb1
   , rt_messages tb2
   WHERE ((("tb1"."uuid" = "tb2"."header_uuid") AND ("tb2"."opcode" = '39')) AND ("tb2"."type" = 'event'))
   ORDER BY "tb1"."innerid" ASC, "tb1"."date" ASC
)
Run Code Online (Sandbox Code Playgroud)

它给了我以下错误:

您的查询具有以下错误:不支持的配置单元类型:带有时区的时间戳

但是,当我自己运行查询时,它可以正常工作,并且在这里提到From_iso8601_timestamp 作为有效的日期函数。

谁能告诉我我在做什么错?

Dav*_*vos 9

不幸的是,雅典娜并不完全支持Presto的所有功能,它具有局限性,并且在技术上比Presto落后几个版本。有一些尝试使Athena与AWS Glue Metastore紧密集成,而AWS Glue Metastore基于Hive的metastore有一些不一致之处。我希望Spark,Hive,Glue,Athena,Presto等能够与同一个metastore一起使用,这样会使生活变得更轻松,但是回到您的问题:

这份有关Presto的较旧Teradata分支的文档提到了presto中的时间戳问题:

Presto声明带/不带时区的时间戳的方法不是sql标准。在Presto中,两者都使用单词TIMESTAMP声明,例如TIMESTAMP'2003-12-10 10:32:02.1212'或TIMESTAMP'2003-12-10 10:32:02.1212 UTC'。确定时间戳是带时区还是不带时区,具体取决于您是否在时区末包括时区。在其他系统中,时间戳显式声明为TIMESTAMP WITH TIME ZONE或TIMESTAMP WITHTIME TIME ZONE

Athena派生的Presto版本确实支持这两种版本timestamptimestamp with timezone但具有teradata文档中提到的怪异功能,这不应该成为问题。真正的问题是Athena不支持带timezone的时间戳

您链接到的presto文档显示该函数返回该不受支持类型的值timestamp with timezone,因此您需要将其强制转换为其他受支持的类型。Athena允许函数和强制转换为随后不受支持的数据类型是一种疏忽,希望可以对此进行补救,但是现在您必须解决它。

您需要做的是CAST()在该函数调用周围使用该函数,这会将类型从更改timestamp with time zonetimestamp

不幸的是,您可能无法将字符串直接转换为时间戳,尽管这取决于字符串的格式。您也不能使用在timestamp字符串之前编写的强制转换样式,例如timestamp '2018-01-01 15:00:00'由于我将在下面解释的原因而无法使用。

from_iso1601_timestamp()函数返回的类型

SELECT typeof("real_date") AS real_date_type
FROM
(
SELECT From_iso8601_timestamp('2018-01-01T15:00:00Z') as "real_date"
)
Run Code Online (Sandbox Code Playgroud)

带时区的时间戳

这不行

SELECT typeof("real_date") AS real_date_type
FROM
(
SELECT CAST('2018-01-01T15:00:00Z' AS timestamp) as "real_date"
)
Run Code Online (Sandbox Code Playgroud)

SQL错误[FAILED]:INVALID_CAST_ARGUMENT:无法将值强制转换为时间戳

这种类型的转换也会返回带有时区的时间戳记:(

请注意,此方法的SELECT部分​​有效,并且说它是timestamp,但是由于某些内部不一致的原因,您无法创建视图,并且会收到错误消息。

CREATE OR replace VIEW test 
AS 
SELECT typeof( "real_date" ) AS real_date_type
FROM
(
SELECT  timestamp '2018-01-01 15:00:00' as "real_date"
)
Run Code Online (Sandbox Code Playgroud)

SQL错误[FAILED]:无法初始化类com.facebook.presto.util.DateTimeZoneIndex

无论出于何种原因,创建视图都需要java类,而在select中解析值时则不需要。这是一个应该解决的错误。

这行不行

CREATE OR REPLACE VIEW test
AS
SELECT typeof("real_date") AS real_date_type
FROM
(
SELECT CAST(From_iso8601_timestamp('2018-01-01T15:00:00Z') AS timestamp) as "real_date"
)
Run Code Online (Sandbox Code Playgroud)


小智 5

我最近正在做的事情遇到了类似的事情。AWS Support 向我推荐了 Davos 解决方案,但它最终并没有适合我的案例。最终对我起作用的解决方案是:

create or replace view db_name.vw_name AS
select
    from_unixtime(cast(to_unixtime(current_timestamp) AS bigint)) as field_name
from db_name.tbl_name
Run Code Online (Sandbox Code Playgroud)

这会将其输出转换current_timestamptimestamp with time zonetimestamp

如果要验证字段的数据类型,可以使用:

select typeof(field_name) from db_name.vw_name
Run Code Online (Sandbox Code Playgroud)

希望有帮助!


Mao*_*ron 5

您可以在 Athena 中通过 Timestamp 数据类型 (dt) 使用以下语法:

SELECT id,dt,dt AT TIME ZONE 'America/New_York' as dateTimeNY FROM Table
Run Code Online (Sandbox Code Playgroud)