digdagを使ってログから中間テーブルを起こそうとした時に起きた話です。
hiveの独特な書き方みたいなところで引っかかりました。
結論
with句が終わって実際にselectするところに
-- DIGDAG_INSERT_LINEを突っ込め!
やろうとしたこと
すでにTD上にある大量レコードのテーブルから、サマリーをした中間テーブルを作ろうとしました。
before(実データではtimeはtimestampではなくlongが入ってます)
| user_id | event | time |
|---|---|---|
| 1 | add | 2017/12/17 06:34 |
| 1 | add | 2017/12/17 06:35 |
| 1 | change | 2017/12/17 06:36 |
| 1 | add | 2017/12/17 06:37 |
| 1 | delete | 2017/12/17 06:49 |
| 1 | add | 2017/12/18 06:50 |
after
| user_id | event | date | count |
|---|---|---|---|
| 1 | add | 2017/12/17 | 3 |
| 1 | add | 2017/12/18 | 1 |
| 2 | add | 2017/12/17 | 1 |
こんな感じ。
抽出クエリ
with log as (
select
user_id
,event
,td_time_format(time,'yyyy-MM-dd','jst') as date
from
event_log
)
select
user_id
,event
,date
,count(1)
from
log
group by
1,2,3,
なんてことはないですね。
実際にtd上で実行しても通りました。
digってみる
timezone: Asia/Tokyo
+transport_raw:
_export:
td:
source_db: test
to_db: event_log
+drip_user_event_cnt:
td>: queries/user_event_cnt.sql
database: ${td.source_db}
engine: hive
create_table: ${td.to_db}.user_event_cnt
td wf run --rerun user_event_cnt.dig
えいっ!
…
あれエラー出ましたね。
FAILED: ParseException line 2:0 cannot recognize input near 'with' 'log' 'as' in select clause MapReduce time taken: 0.195 seconds
予約語関連でエラー?そんなバカな
というわけで、もろもろ調べてみました。
原因判明
digdagのcreate_tableコマンドが何をしているかというと、
指定したsqlの前にこの一文を発行しているようです。
```INSERT OVERWRITE TABLE test .`user_event_cnt`
`INSERT`の後に`WITH`句がおけないという`hive`のローカルルールに引っかかりエラーが起きていました。
実際に`select`をするところの前に`-- DIGDAG_INSERT_LINE`を記述してあげないといけません。
```sql:user_event_cnt.sql
with log as (
select
user_id
,event
,td_time_format(time,'yyyy-MM-dd','jst') as date
from
event_log
)
-- DIGDAG_INSERT_LINE
select
user_id
,event
,date
,count(1)
from
log
group by
1,2,3,
これでおっけい!
実行結果もうまくいきました。
余談
tdといえば、クエリをprestoとhiveで選べますが、presto ではどうなってるでしょうか。
prestoでは、withの前でinsertが記述されても特に問題なく実行されます。
なので気にせずにinsertとできると思います。
hiveでクエリ書き換えたけど動かねーぞ!となったら、ぜひ試してみてください。