私はHiveを使用しており、次のような構造のテーブルがあります。
CREATE TABLE t1 (
id INT,
created TIMESTAMP,
some_value BIGINT
);
t1
で、180日未満のすべての行を見つける必要があります。次のクエリでは、検索述語に一致するデータがテーブルに存在していても、行は生成されません。
select *
from t1
where created > date_sub(from_unixtime(unix_timestamp()), 180);
Hiveで日付比較を実行する適切な方法は何ですか?
どうですか:
_where unix_timestamp() - created < 180 * 24 * 60 * 60
_
日付の計算は、実際のタイムスタンプ値だけで実行できる場合、通常は最も簡単です。
それとも丸一日だけ遮断したいですか?次に、問題は、intとstringの間で前後に変換する方法にあると思います。試してください:
_where created > unix_timestamp(date_sub(from_unixtime(unix_timestamp(),'yyyy-MM-dd'),180),'yyyy-MM-dd')
_
各UDFを歩く:
unix_timestamp()
はintを返します:エポック以降の秒単位の現在の時間from_unixtime(,'yyyy-MM-dd')
は、指定された形式の文字列に変換します。 「2012-12-28」date_sub(,180)
は、その文字列から180日を減算し、同じ形式で新しい文字列を返します。unix_timestamp(,'yyyy-MM-dd')
は、その文字列をintに変換しますそれがすべて面倒になりすぎている場合は、いつでもUDFを記述して自分で行うことができます。
あるいは、datediffを使用することもできます。次にwhere句は
文字列のタイムスタンプの場合(jdbc形式):
datediff(from_unixtime(unix_timestamp()), created) < 180;
unixエポック時間の場合:
datediff(from_unixtime(unix_timestamp()), from_unixtime(created)) < 180;
多分それはtimestampタイプを扱うHiveのバグだと思います。私は最近それを使おうとして、間違った結果を得ています。文字列の代わりにタイムスタンプを使用するようにスキーマを変更し、値を
yyyy-MM-dd HH:mm:ss
フォーマット、それから選択クエリが私のために働いた。
ドキュメントによると、Hiveはエポック秒を表すBIGINTをタイムスタンプに変換できる必要があり、既存のすべての日時UDFがタイムスタンプデータ型で機能する必要があります。
次の簡単なクエリを使用します。
test_tt制限1からfrom_unixtime(unix_timestamp())、cast(unix_timestamp()をタイムスタンプとして)を選択します。
私は両方のフィールドが同じであることを期待しますが、私は得ます:
2012-12-29 00:47:43 1970-01-16 16:52:22.063
他の奇妙さも見ています。
TIMESTAMPはミリ秒です
unix_timestampは秒単位です
RHSに1000を掛ける必要があります。
where created > 1000 * date_sub(from_unixtime(unix_timestamp()), 180);
これを確認し、 Hive で15分未満の日付の差を参照した後、私は解決策を思いつきました。 Hiveが日付の比較を文字列として効果的に実行しない理由はわかりませんが(辞書順に並べ替えて比較する必要があります)、次の解決策が機能します。
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 ;