行毎にカラムの意味の異なるCSVを処理する必要があったのでメモ
そんな特殊なCSVにめぐり合う機会も少ないだろうけど...
導入
問題は行毎にカラムの意味が異なる事に加え、カラムの数が異なるということだった。
最初は下記のように単純にカラムの最大数に合わせテーブル定義を作成していた。
CREATE TABLE csv_test(
item01 STRING,
item02 STRING,
item03 STRING,
item04 STRING
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ',';
みたいな感じで。
データも数値か文字かもわからないのでとりあえず全部STRINGで定義。
うーん、CSVのカラム数が変わる度にテーブル定義変えたりするのはあまり賢く無いし、だからといってitem100まで事前に作っとけばいいかというとそういう問題でもないし、そもそもカラムの名前がイカしてない。
という事で、しばし考えた後、ARRAYにすれば良い事に気付く。
create table csv_test(
items ARRAY<string>
)
ROW FORMAT DELIMITED
COLLECTION ITEMS TERMINATED BY ',';
これであれば、
SELECT items[0] FROM csv_test;
とやって任意のカラムにアクセス可能である。
行毎にカラム数が違う場合にも、
SELECT items[10] FROM csv_test WHERE size(items) >= 10;
みたいな書き方も出来る。
発展形
下記のようなデータで、先頭のカラムに入っている値を元に後方のカラムの値を取る方法を考えてみる。
1,HOGE,HUGA,HIGE
2,HIGE,HOHO,HIHI
2,HIHI,HOHO,HIGE
0,HUHU,HUHU,HOGE
indexは0スタートとすることとした場合、例えば、一行目はHUGA
、二行目はHIHI
を取りたいといった具合だ。
いやいや、難しくないでしょ、、、
ということで、下記のように書いてみた。
SELECT items[cast(items[0] as int)] FROM csv_test;
エラった。
配列の添字に動的な値を取ることは出来ないとのこと。
本件、下記にも上がっていた。
https://issues.apache.org/jira/browse/HIVE-1955
issueとしては上がっているものの2012年から更新無いね。見放されてるかな?
しかし、ネイティブではサポートされていないけど、UDF作ればできるけどねって言ってるね(・∀・)
さてさて、いよいよUDFか。次回に続く。