dbt と Teradata Vantage によるデータ変換

[Medium 掲載記事 - Data transformation with dbt and Teradata Vantage](https://medium.com/teradata/data-transformation-with-dbt-and-teradata-vantage-58babcccffa7) [2025/02/12時点]の翻訳です。

:::note information
各機能の詳細な説明に関しては、段階的にリンクを追加していきますので、リンクから詳細ページを参照してご利用下さい。
:::

dbt (データ ビルド ツール) は、モダン データ スタックの基盤となるデータ変換ツールです。この投稿では、dbt を使用して Teradata Vantage データ ウェアハウスでデータを変換する方法について説明します。

dbt は、ELT (抽出、ロード、変換) の T を処理します。他のプロセスによって生データがデータ ウェアハウスまたはデータ レイクに取り込まれることが前提となります。次に、このデータを、第 3 正規形、データ ボールト、または選択したその他の実装など、選択した内部表現に変換する必要があります。最後に、内部表現を、データ コンシューマーが使用するツールで必要な使用可能な形式に変換する必要があります。これは、BI ツールのディメンション モデルである場合もあれば、AI/ML 処理の機能などの他のカスタム形式である場合もあります。dbt を使用すると、SQL を使用してデータを操作し、git を使用して変換をバージョン管理し、dbt データ テストを使用してデータ パイプラインの結果を検証することで、データ ウェアハウスまたはデータ レイク内でこれらすべての変換を実行できます。

dbt には、Jaffle Shop というサンプル プロジェクトがあります。このプロジェクトでは、生の入力データ (顧客セット、注文セット、支払いセット) が BI ツールで使用できるディメンション モデルに変換される様子を示します。

出発点は次のとおりです。

##### 入力データセット #####
<img width="900" alt="入力データセット.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740723/7ae13ef9-b144-4cbf-af85-cd384ee63637.png">

必要な出力モデルは次のとおりです。

##### 必要な結果次元モデル #####
<img width="550" alt="Scikit-learn.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740723/b9c79fc6-e389-43ce-8f6a-462821f7aa22.png">

ご覧のとおり、顧客ディメンションでは集計 (first_order、most_recent_order、number_of_orders、total_order_amount) を行う必要があり、ファクト テーブルではOrdersテーブルとpaymentsテーブル間の結合が必要です。

元の Jaffle Shop プロジェクトでは、Google BigQuery を使用しています。プロジェクトを https://github.com/Teradata/jaffle_shop-dev にフォークし、SQL を Teradata 構文に合わせて調整するためにいくつかの変更を加えました。ここでは、サンプル プロジェクトが適用するモデル (後続の変換) について説明します。

まず、ソース テーブルに基づいてステージング テーブルを作成します。この例では、生データ セットが単純なので、この手順は簡単です。実際には、この手順では通常、データ形式の正規化、命名規則の調整、データ単位の変更が行われます。この場合は、生テーブルから選択します。例:

```
with source as (

    {#-
    Normally we would select from the table here, but we are 
    using seeds to load our data in this project
    #}
    select * from {{ ref('raw_customers') }}

),

renamed as (

    select
        id as customer_id,
        first_name,
        last_name,
        email

    from source

)

select * from renamed
```


この変換、または dbt 用語ではモデルが共通テーブル式 (CTE) 構文に依存していることに注意してください。CTE は、複雑な SQL を分解するクリーンな方法を提供します。CTE について復習する必要がある場合は、Teradata Vantage — SQL データ操作言語のドキュメントを参照してください。

これで、入力データ セットがステージングされたので、結合と集計を実行します。

まず、ユーザーごとordersデータを集計します (後の手順でこのモデルを customer_orders と呼びます)。

```
with orders as (

    select * from {{ ref('stg_orders') }}

),

final as (

    select
        customer_id,

        min(order_date) as first_order,
        max(order_date) as most_recent_order,
        count(order_id) as number_of_orders
    from orders

    group by 1

)

select * from final
```

ordersテーブルとpaymentsテーブルを結合します (customer_payments):

```
with payments as (

    select * from {{ ref('stg_payments') }}

),

orders as (

    select * from {{ ref('stg_orders') }}

),

final as (

    select
        orders.customer_id,
        sum(amount) as total_amount

    from payments

    left join orders on payments.order_id = orders.order_id

    group by 1

)

select * from final
```

最後に、注文ごとに支払いを集計します (order_payments)。


```
{% set payment_methods = ['credit_card', 'coupon', 'bank_transfer', 'gift_card'] %}

with payments as (

    select * from {{ ref('stg_payments') }}

),

final as (

    select
        order_id,

        {% for payment_method in payment_methods -%}
        sum(case when payment_method = '{{payment_method}}' then amount else 0 end) as {{payment_method}}_amount,
        {% endfor -%}

        sum(amount) as total_amount

    from payments

    group by 1

)

select * from final
```

これらの中間モデルを使用して、出力ディメンション モデルの構築を開始します。

customers、customer_orders、customer_payments モデルを取得し、customers ディメンションを構築します。

```
with customers as (

    select * from {{ ref('stg_customers') }}

),

customer_orders as (

    select * from {{ ref('customer_orders') }}

),

customer_payments as (

    select * from {{ ref('customer_payments') }}

),

final as (

    select
        customers.customer_id,
        customer_orders.first_order,
        customer_orders.most_recent_order,
        customer_orders.number_of_orders,
        customer_payments.total_amount as customer_lifetime_value

    from customers

    left join customer_orders on customers.customer_id = customer_orders.customer_id
    left join customer_payments on customers.customer_id = customer_payments.customer_id

)

select * from final
```

最後に、orders モデルと order_payments モデルを使用してファクト テーブルを構築します。

```
{% set payment_methods = ['credit_card', 'coupon', 'bank_transfer', 'gift_card'] %}

with orders as (

    select * from {{ ref('stg_orders') }}

),

order_payments as (

    select * from {{ ref('order_payments') }}

),

final as (

    select
        orders.order_id,
        orders.customer_id,
        orders.order_date,
        orders.status,

        {% for payment_method in payment_methods -%}

        order_payments.{{payment_method}}_amount,

        {% endfor -%}

        order_payments.total_amount as amount

    from orders

    left join order_payments on orders.order_id = order_payments.order_id

)

select * from final
```

モデルを設定したら、dbt を実行しましょう。

まず、CSV ファイルからサンプル データを入力テーブルに読み込みます。
```
dbt seed
```
これで変換を実行する準備が整いました。
```
dbt run
```
サンプル プロジェクトには、変換の各ステップでデータを検証するサンプル テストが含まれています。テストは次のように実行できます。
```
dbt test
```

dbt はすべてのデータ変換を認識しているため、クリーンな系統ドキュメントを作成できます。次のコマンドを実行すると、
```
dbt docs generate
dbt docs serve
```
次の系統グラフを含むモデルのドキュメントが提供されます。

#### dbt によって作成されたデータ系統図 ####
<img width="700" alt="Scikit-learn.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740723/ef2c6c10-3af4-402d-a04f-c7c5e1baddab.png">

この投稿では、dbt の用途について説明しました。生の入力データを取得して BI ツールに役立つディメンション モデルを生成するサンプル プロジェクトについて説明しました。

次のステップ:

* dbt のインストール、サンプル プロジェクトのクローン作成、手順の実行方法については、[Teradata Vantage を使用した dbt のチュートリアル](https://developers.teradata.com/ja/quickstarts/manage-data/dbt/)を参照してください。
*dbt Teradata アダプターの詳細については、[dbt-teradata プラグインのドキュメント](https://github.com/Teradata/dbt-teradata)を参照してください。

## おわりに
:::note warn
警告
この本書は[Teradata Vantageドキュメンテーション](https://docs.teradata.com/)よりトピックに必要な情報を抜粋したものです。掲載内容の正確性・完全性・信頼性・最新性を保証するものではございません。正確な内容については、原本をご参照下さい。
また、修正が必要な箇所や、ご要望についてはコメントをよろしくお願いします。
:::

#### Teradataへのお問合せ
[Teradataへのお問合せ](https://www.teradata.jp/About-Us/Contact)