Je travaille avec Hive et j'ai un tableau structuré comme suit:
CREATE TABLE t1 (
id INT,
created TIMESTAMP,
some_value BIGINT
);
Je dois trouver chaque ligne dans t1
datant de moins de 180 jours. La requête suivante ne génère aucune ligne même si la table contient des données correspondant au prédicat de recherche.
select *
from t1
where created > date_sub(from_unixtime(unix_timestamp()), 180);
Quelle est la manière appropriée d'effectuer une comparaison de date dans Hive?
Que diriez-vous:
where unix_timestamp() - created < 180 * 24 * 60 * 60
Le calcul des dates est généralement le plus simple si vous pouvez le faire avec les valeurs d’horodatage réelles.
Ou voulez-vous qu'il soit coupé uniquement des jours entiers? Ensuite, je pense que le problème réside dans la façon dont vous effectuez la conversion entre les ints et les chaînes. Essayer:
where created > unix_timestamp(date_sub(from_unixtime(unix_timestamp(),'yyyy-MM-dd'),180),'yyyy-MM-dd')
En parcourant chaque UDF:
unix_timestamp()
renvoie une int: heure actuelle en secondes depuis Epochfrom_unixtime(,'yyyy-MM-dd')
est converti en une chaîne du format donné, par exemple. '2012-12-28'date_sub(,180)
soustrait 180 jours de cette chaîne et renvoie une nouvelle chaîne au même format.unix_timestamp(,'yyyy-MM-dd')
reconvertit cette chaîne en un entierSi tout cela devient trop poilu, vous pouvez toujours écrire un fichier UDF pour le faire vous-même.
Alternativement, vous pouvez aussi utiliser datiff . Ensuite, la clause where serait
en cas d'horodatage de chaîne (format jdbc):
datediff(from_unixtime(unix_timestamp()), created) < 180;
en cas de temps Unix:
datediff(from_unixtime(unix_timestamp()), from_unixtime(created)) < 180;
Je pense que c’est peut-être un bogue Hive qui concerne le type timestamp. J'ai essayé de l'utiliser récemment et d'obtenir des résultats incorrects. Si je change votre schéma pour utiliser une chaîne au lieu de timestamp, et fournir des valeurs dans le
aaaa-MM-jj HH: mm: ss
format, puis la requête de sélection a fonctionné pour moi.
Selon la documentation, Hive devrait être en mesure de convertir un BIGINT représentant des secondes d’époque en un horodatage, et que tous les fichiers UDF datetime existants fonctionnent avec le type de données d’horodatage.
avec cette requête simple:
sélectionnez from_unixtime (unix_timestamp ()), transformez (unix_timestamp () en tant qu'horodatage ) à partir de test_tt limite 1;
Je m'attendrais à ce que les deux champs soient identiques, mais je reçois:
2012-12-29 00:47:43 1970-01-16 16: 52: 22.063
Je vois aussi d'autres bizarreries.
TIMESTAMP est en millisecondes
unix_timestamp est en secondes
Vous devez multiplier le RHS par 1000.
where created > 1000 * date_sub(from_unixtime(unix_timestamp()), 180);
Après avoir examiné cela et fait référence à Date Difference moins de 15 minutes dans Hive j’ai trouvé une solution. Bien que je ne sois pas sûr de savoir pourquoi Hive n'effectue pas la comparaison de manière efficace sur les dates sous forme de chaînes (elles doivent trier et comparer lexicographe), la solution suivante fonctionne:
FROM (
SELECT id, value,
unix_timestamp(created) c_ts,
unix_timestamp(date_sub(from_unixtime(unix_timestamp()), 180), 'yyyy-MM-dd') c180_ts
FROM t1
) x
JOIN t1 t ON x.id = t.id
SELECT to_date(t.Created),
x.id, AVG(COALESCE(x.HighestPrice, 0)), AVG(COALESCE(x.LowestPrice, 0))
WHERE unix_timestamp(t.Created) > x.c180_ts
GROUP BY to_date(t.Created), x.id ;