この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは!エノカワです。
Snowflakeでは、データをテーブルにロードする際のデータ変換をサポートしています。
こちらの記事でステージにあるファイルのデータのクエリを紹介しましたが、
クエリの結果をCOPY
コマンドでテーブルにロードするイメージです。
今回はロード中のデータ変換を実際に試してみました。
準備
サンプルデータベースSNOWFLAKE_SAMPLE_DATA
のTPCH_SF1.ORDERS
を利用します。
TPCH_SF1.ORDERS
のデータをステージのCSVファイルにアンロードし、
別のテーブルにロードする際にデータ変換を試してみましょう。
Snowsightのワークシート上で、以下のクエリを実行していきます。
ウェアハウス作成
検証で使用するウェアハウスDEMO_WH
を作成します。
create or replace warehouse DEMO_WH with
WAREHOUSE_SIZE = 'XSMALL'
;
use warehouse DEMO_WH;
データベース作成
検証で使用するデータベースDEMO_DB
を作成します。
create or replace database DEMO_DB;
use DEMO_DB;
ステージ作成
CREATE STAGE
コマンドでアンロード先のステージを作成します。
今回は名前付きステージを使用します。
create or replace stage ORDERS_UNLOAD_STAGE;
データのアンロード
TPCH_SF1.ORDERS
からデータをアンロードします。
アンロード先は作成した名前付きステージORDERS_UNLOAD_STAGE
です。
アンロード後、LIST
コマンドでステージングされたファイルのリストを取得します。
copy into @ORDERS_UNLOAD_STAGE
from SNOWFLAKE_SAMPLE_DATA.TPCH_SF1.ORDERS
file_format = (type = CSV compression = 'GZIP');
list @ORDERS_UNLOAD_STAGE;
5個のCSVファイルがアンロードされました。
テーブル作成
TPCH_SF1.ORDERS
と同じ構造を持つテーブルを作成します。
作成する前に、TPCH_SF1.ORDERS
のデータをプレビューしておきましょう。
注文ID、金額、注文日、店員などの列を持つ注文データです。
以下のクエリでテーブルを作成します。
テーブル作成後、DESCRIBE
コマンドでテーブルの構造を確認します。
create or replace table SF1_ORDERS
like SNOWFLAKE_SAMPLE_DATA.TPCH_SF1.ORDERS;
describe table SF1_ORDERS;
null?
が全てN(NULL値を許容しない)になっています。
列プロパティ変更
検証でロードしない列が出てくるので、以下4つの列をY(NULL値を許容する)に変更しておきます。
alter table SF1_ORDERS alter (
O_ORDERSTATUS drop not null,
O_ORDERPRIORITY drop not null,
O_SHIPPRIORITY drop not null,
O_COMMENT drop not null
);
describe table SF1_ORDERS;
4つの列(赤枠囲み)がNULL値許容に変更されました。
それでは実際にデータの変換を試してみましょう。
データの変換
テーブルデータのサブセットのロード
データの一部の列をテーブルにロードすることができます。
COPY
コマンドでロード先のカラムを選択、SELECT
ステートメントでロードする列を選択します。
ロード後、SELECT
ステートメントでテーブルの中身を確認します。
copy into SF1_ORDERS(
O_ORDERKEY, O_CUSTKEY, O_TOTALPRICE, O_ORDERDATE, O_CLERK)
from (select
$1, $2, $4, $5, $7 from
@ORDERS_UNLOAD_STAGE)
file_format = (type = CSV);
select * from SF1_ORDERS;
選択した5つの列のみロードされました。
ロードされなかった列はデフォルト値のNULL値が挿入されています。
ロード中の CSV 列の並べ替え
テーブルにロードする前に、ステージングされた CSV ファイルの列データを並べ替えることができます。
さらに、SUBSTR
関数を使用して、文字列を挿入する前に切り出すこともできます。
SELECT
ステートメントで1番目と2番目の列を並び替えてみましょう。
ロード先のカラムの方も同じように1番目と2番目の列を並び替えます。
6番目の列はSUBSTR
関数で先頭1文字を切り出し、O_ORDERPRIORITYにロードします。
truncate table SF1_ORDERS;
copy into SF1_ORDERS(
O_CUSTKEY, O_ORDERKEY, O_TOTALPRICE, O_ORDERDATE, O_CLERK, O_ORDERPRIORITY)
from (select
$2, $1, $4, $5, $7, substr($6,1,1)
from @ORDERS_UNLOAD_STAGE)
file_format = (type = CSV);
select * from SF1_ORDERS;
列を並び替えてロードすることができました。
O_ORDERPRIORITYも1文字だけロードされていますね。
ロード中のデータ型の変換
データのロード中にデータ型を変換することができます。
変換関数TO_BINARY
, TO_NUMBER
, TO_TIMESTAMP_NTZ
で試してみましょう。
変換後のデータをロードする列を用意する必要があるので、
ALTER TABLE
コマンドで3つの列をまとめて追加します。
truncate table SF1_ORDERS;
alter table SF1_ORDERS
add
O_ORDERKEY_BINARY binary,
O_TOTALPRICE_NUMBER number,
O_ORDERDATE_TIMESTAMP timestamp_ntz;
describe table SF1_ORDERS;
3つの列(赤枠囲み)が追加されました。
以下のクエリを実行してみましょう。
copy into SF1_ORDERS(
O_ORDERKEY, O_CUSTKEY, O_TOTALPRICE, O_ORDERDATE, O_CLERK,
O_ORDERKEY_BINARY, O_TOTALPRICE_NUMBER, O_ORDERDATE_TIMESTAMP)
from (select
$1, $2, $4, $5, $7,
to_binary($1, 'utf-8'), to_number($4), to_timestamp_ntz($5)
from @ORDERS_UNLOAD_STAGE)
file_format = (type = CSV);
select
O_ORDERKEY, O_ORDERKEY_BINARY,
O_TOTALPRICE, O_TOTALPRICE_NUMBER,
O_ORDERDATE, O_ORDERDATE_TIMESTAMP
from SF1_ORDERS;
追加した3つの列に変換後のデータがロードされていますね。
まとめ
以上、ロード中のデータ変換を実際に試してみました。
SELECT
ステートメントを使用してサブセットのロードや並び替え、データ型変換をすることができました。
この機能のおかげで、データのロード中に列を並べ替える際に、
一時テーブルを使用して事前に変換されたデータを保存する必要がなくなります。
ETL処理の簡素化に活用できそうですね。