Amazon Athena カラムの中のカンマ区切りデータを複数レコードに分解する

eyecatch_athena

将来的なデータ分析に備えウェブブラウザからPOSTされたデータをそのままファイルやレコードに登録しているケースでは、分析対象のデータのカラムにカンマ区切りデータがそのまま格納されていることがあります。このままではデータ分析用途のデータとして不向きなので、複数レコードに分解する必要があります。 Amazon Athenaでは、split関数と「CROSS JOIN UNNEST」構文を利用して簡単に複数レコードに分解することができます。

サンプルTSVファイル

ファイルはタブ区切りで、3つ目のフィールドがカンマ区切りのフィールドです。今回は6種類のレコードを用意しました。1〜3は正常なカンマ区切りデータです。これだけでは面白くないので、4〜6はあえて異常なカンマ区切りデータを用意しました。

1   ok1 1
2   ok2 2,3
3   ok3 4,5,6
4   ng1 7,
5   ng2 ,8
6   ng3 ,9,

テーブル定義

CREATE EXTERNAL TABLE IF NOT EXISTS comma_data (
id int, 
name string,
categories string
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
WITH SERDEPROPERTIES (
  'serialization.format' = '\t',
  'field.delim' = '\t'
)LOCATION 's3://<bucketname>/comma_data/';

SELECTの例

categoriesカラムを参照するとカンマ区切り文字がそのまま表示されます。

SELECT id, name, categories
FROM comma_data t1;

20170306-amazon-athena-comma-to-records-query1 split関数と「CROSS JOIN UNNEST」構文を利用して、categoriesカラムのデータをカンマ「,」区切りして、categoryカラムの複数レコードとして分割します。

SELECT id, name, category
FROM comma_data t1
  CROSS JOIN UNNEST(
    split(t1.categories, ',')
  ) AS t (category)
;

カンマ区切り文字が複数レコードに分解されました。カンマのみの場合は値がないカラムとして出力されています。 20170306-amazon-athena-comma-to-records-query2-1

値がないカラムのレコードを取り除くには、「category IS NOT NULL」ではなく、「category <> ''」と指定します。categoryはNULLではないようです。

SELECT id, name, category
FROM comma_data t1
  CROSS JOIN UNNEST(
    split(t1.categories, ',')
  ) AS t (category)
WHERE category <> ''
;

20170306-amazon-athena-comma-to-records-query3

最後に

正常なカラムデータではない場合でもエラーにならずレコードとして分解されることが確認できました。データ分析の要件に合わせ必要に応じて、不要なレコードを除去する条件を指定することができるので、簡易なETLにも活用できそうです。