Azure Data Factory / Synapse  Mapping DataflowでSCD2データを生成する

## はじめに

Mapping Dataflowでscd type2を生成する方法を記載します。

## 参考

ナレッジセンターにて、scd type1/type2については更新処理による実装が確認可能です。

scdについて

https://www.kimballgroup.com/?s=scd&search=

日本語の記事少ないですね

https://knowledge.insight-lab.co.jp/sisense/data-modeling/slowly_changing_dimension

https://docs.microsoft.com/ja-jp/power-bi/guidance/star-schema#type-2-scd

https://docs.microsoft.com/ja-jp/learn/modules/populate-slowly-changing-dimensions-azure-synapse-analytics-pipelines/2-describe


## 今回の実装の特徴

以下の記事でも語られるように、更新、挿入型のscd の実装は、日付順にデータを更新していくようなパイプラインを構成することが多く、再実行や、履歴の差し込みの難易度が非常に高いです。

https://docs.microsoft.com/ja-jp/learn/modules/populate-slowly-changing-dimensions-azure-synapse-analytics-pipelines/2-describe

今回の実装では、すべてのデータからscd type2型のデータをバッチ生成することで再実行に強いパイプラインとなります。

ただし、このデータをスタースキーマのディメンションとしてサロゲートキーとともに利用する場合、関連のすべてのfactおよび、ディメンション自身で全データを利用した処理となるため、非常に処理負荷の高い実装となります。

したがって、今回紹介する方式は小規模なディメンショナルモデルであるか、sparkなど大幅なスケールアップが可能なバッチ処理基盤での利用をお勧めします。

### ちなみに

ディメンションはvalid_to , valid_fromで範囲検索させたり、updateを伴うものじゃなくて毎日スナップショットを作ろうぜという考え方もあります。

https://towardsdatascience.com/building-a-modern-batch-data-warehouse-without-updates-7819bfa3c1ee

https://www.youtube.com/watch?v=4Spo2QRTz1k&t=989s

## 手順

### 0. データと環境の準備

[Azure Data Factory or Synapse Mapping Dataflowの変更フィードの紹介](https://qiita.com/ryoma-nagata/items/dd318582e19394a90550?utm_campaign=post_article&utm_medium=twitter&utm_source=twitter_share)

で利用したデータを利用してみます。

rawはこの状態です。

![2022-03-31-17-42-29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/8fece95a-468d-d8a7-cfe8-0f73124b70b8.png)

データセットも使いまわします。

![2022-03-31-17-43-31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/0a33de60-88e7-74c9-5101-5a2bd0eea56a.png)

### 1. Mapping Dataflowの作成

1 ソースを追加します。

![2022-03-31-17-44-48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/989067d0-5ea0-6038-dc4e-fbf36c2869e8.png)

2 ファイルネームに連携日が含まれているので設定します。

![2022-03-31-17-45-13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/784b16ef-e6ba-8728-f4e5-7e143018dbb5.png)

3 プレビューを確認します。

![2022-03-31-17-46-17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/35331ad9-9d1c-ad9c-0a72-fbf656880f9b.png)

4 パラメータを設定します。

![2022-03-31-17-48-27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/bb70ee6d-28f5-52ec-bbb1-e6125617045d.png)

5 キーハッシュ列、データハッシュ列、日付列を追加します。

![2022-03-31-17-54-40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/485cb68d-86e9-ddb6-1a0e-76fdb43c7cc5.png)


pk_hash：

キー列からハッシュ値を生成します

```

md5(byName($PrimaryKey))

```

data_hash:

データ列からハッシュ値を生成します。


```

md5(byNames(split($Columns,',')))

```

valid_from:

データの有効開始日となります。

```

toDate(split(filename, '_')[3],'yyyyMMdd')

```

プレビューはこんな感じ

![2022-03-31-17-55-07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/086b31a2-7761-75cc-145c-ba8ef7af4565.png)

6 ID=2については変更していないことがわかります。これは同じvalid_from(開始日)にしたいので集約をかけます。

※ハッシュ列の付与も含め、変更データのみがファイル連携される基盤であれば、この集約は不要となります。

![2022-03-31-17-56-56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/96187d7b-383e-6c79-6d8e-3cb2dc032a4f.png)

![2022-03-31-17-57-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/5669d148-09b8-9496-88b2-655929fb66c0.png)


変更のあったデータのみが2行となりました

![2022-03-31-17-57-52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/030bff10-4fe4-314d-3bcb-97500c193b5a.png)


7 集約結果と自己結合をして、必要なデータのみにしぼります。

![2022-03-31-17-59-18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/db5ea04e-d231-2b43-a185-44f80cb6c095.png)


8 select で列を調整します。

![2022-03-31-18-14-16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/74dfe94b-724d-de30-9d52-00ccbb150ca7.png)



9 いよいよvalid to を生成します。windowを追加します。

over : 

![2022-03-31-18-06-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/278d997d-1b59-5daf-0896-650b1550e1e9.png)

並び替え：

![2022-03-31-18-06-25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/ef77e9c2-8ad8-5743-3934-c6df7f3a4c2f.png)


範囲：

![2022-03-31-18-06-35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/a6235b60-7798-dd91-be45-deaf18b2818b.png)

ウィンドウの列：

![2022-03-31-18-10-16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/2778e1e3-975d-29af-d679-659a667b2129.png)

```

addDays(lag(valid_from, 1, null()),-1)

```

valid_toが次のvalid_fromの前日となるようにしています。

プレビューをみます。

![2022-03-31-18-09-13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/1d7a6f4a-0d46-210c-a99f-8662460b521f.png)

10 全件処理なので、シンクは上書きするように構成しましょう

![2022-03-31-18-12-50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/d9659389-cdca-d9e8-4208-41b0d53dfff2.png)

### 2. 結果の確認

パイプライン実行後、ファイルを確認してみます。

![2022-03-31-18-15-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/27db2ba1-704d-082f-c0d7-1c7e8b1c1366.png)