web-dev-qa-db-fra.com

la conversion en horodatage avec fuseau horaire a échoué sur Athena

J'essaie de créer la vue suivante:

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
)

et cela me donne l'erreur suivante:

Votre requête contient les erreurs suivantes: Type de ruche non pris en charge: horodatage avec fuseau horaire

cependant, lorsque j'exécute la requête seule, cela fonctionne très bien, et le From_iso8601_timestamp est mentionné ici comme une fonction de date valide.

quelqu'un peut-il me dire ce que je fais mal?

6
Gal Itzhak

Malheureusement, Athena ne prend pas entièrement en charge toutes les fonctionnalités de Presto, il a limitations et est techniquement quelques versions derrière Presto. Il y a une tentative pour faire en sorte qu'Athena s'intègre étroitement avec l'AWS Glue Metastore, qui, bien que basé sur le métastore de Hive, présente quelques incohérences. Je souhaite que Spark, Hive, Glue, Athena, Presto et al fonctionnent simplement avec le même métastore, cela leur faciliterait la vie, mais revenons à votre problème:

Ce document sur une ancienne fourchette de teradata de Presto mentionne quelques problèmes avec l'horodatage dans presto:

La méthode de Presto pour déclarer les horodatages avec/sans fuseau horaire n'est pas standard SQL. Dans Presto, les deux sont déclarés à l'aide de Word TIMESTAMP, par ex. TIMESTAMP '2003-12-10 10: 32: 02.1212' ou TIMESTAMP '2003-12-10 10: 32: 02.1212 UTC'. L'horodatage est déterminé avec ou sans fuseau horaire selon que vous incluez un fuseau horaire à la fin de l'horodatage. Dans d'autres systèmes, les horodatages sont explicitement déclarés comme TIMESTAMP WITH TIME ZONE ou TIMESTAMP WITHOUT TIME ZONE

La version de Presto dont Athena est issue prend en charge à la fois timestamp et timestamp with timezone Mais avec cette bizarrerie comme mentionné dans les documents de teradata qui ne devrait pas être un problème. Le vrai problème est que Athena ne prend pas en charge l'horodatage avec le fuseau horaire .

Les documents presto que vous avez liés pour montrer que la fonction renvoie une valeur de ce type non pris en charge timestamp with timezone, Vous devez donc la convertir en quelque chose d'autre qui est pris en charge. C'est un oubli qu'Athena autorise les fonctions et la diffusion vers un type de données qui n'est alors pas pris en charge, et j'espère que cela sera corrigé, mais pour l'instant vous devez contourner ce problème.

Ce que vous devez faire est d'utiliser la fonction CAST() autour de cet appel de fonction, qui changera le type de timestamp with time zone En timestamp

Malheureusement, vous ne pouvez probablement pas convertir la chaîne directement en horodatage, bien que cela dépende de la façon dont la chaîne est formatée. Vous ne pouvez pas non plus utiliser le style de transtypage où vous écrivez timestamp avant la chaîne, par exemple ne peut pas faire timestamp '2018-01-01 15:00:00' pour les raisons que je vais expliquer ci-dessous.

Type retourné par la fonction from_iso1601_timestamp()

SELECT typeof("real_date") AS real_date_type
FROM
(
SELECT From_iso8601_timestamp('2018-01-01T15:00:00Z') as "real_date"
)

horodatage avec fuseau horaire

Ça ne marche pas

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

Erreur SQL [FAILED]: INVALID_CAST_ARGUMENT: la valeur ne peut pas être convertie en horodatage

Ce style de Casting renvoie également l'horodatage avec le fuseau horaire :(

Notez que la partie SELECT de cela fonctionne, et elle indique qu'il s'agit d'un timestamp, mais pour une raison d'incohérence interne, vous ne pouvez pas créer une vue et vous obtiendrez une erreur.

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"
)

Erreur SQL [FAILED]: impossible d'initialiser la classe com.facebook.presto.util.DateTimeZoneIndex

Pour une raison quelconque, la création d'une vue nécessite que la classe Java tout en analysant la valeur dans la sélection ne le fasse pas. C'est un bogue qui doit être corrigé.

Cela fonctionne bien

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"
)
9
Davos

Vous pouvez utiliser la syntaxe suivante dans Athena sur le type de données Timestamp (dt):

SELECT id,dt,dt AT TIME ZONE 'America/New_York' as dateTimeNY FROM Table
1
Maor Aharon

Ran en quelque chose de similaire sur quelque chose que je travaillais récemment. Le support AWS m'a indiqué la solution de Davos mais elle n'a pas fini par fonctionner pour mon cas. La solution qui a fini par fonctionner chez moi était:

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

Cela convertira la sortie de current_timestamp lequel est timestamp with time zone à timestamp

Si vous souhaitez vérifier le type de données du champ, vous pouvez utiliser:

select typeof(field_name) from db_name.vw_name

J'espère que cela pourra aider!

1
Andrew Madsen