Power BIで複合主キーを扱う

# 本記事の目的
Power BIを使っていて意外だったことに、「複合主キーに対するリレーションがはれない」ということがありました。
社内の業務システムでは複合主キーが多用されていて、結構困ります...。

他の方がどのように対処されているか気になっていますが、現状、解決策を残しておきますが、少し手間がかかります。
もっと賢い方法がありましたらアドバイスよろしくお願いします。

# 複合主キーとは

**複合主キーとは複数のキーの組み合わせからなる主キー**のことです。
（データモデルについては [別記事](https://qiita.com/ryokita/items/b0656ffa572507b831b5) で投稿しました。）

例として、全社で管理されている以下のような課題リストを想定します。
<img width="363" alt="スクリーンショット 2020-04-21 23.06.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/b505e034-e690-e374-89ea-3b8685803a04.png">

ここでは様々なプロジェクトの課題を1つの表で管理しています（混沌）。

XXXプロジェクトとYYYプロジェクトでは、同じ課題ID「001」があります。
つまり課題のIDはプロジェクトごとに、別々に採番されていることが分かります。

言い換えると、この会社では「プロジェクト」と「課題ID」の両方を聞いて初めて、どの課題のことを指しているのか特定することができます。
<img width="371" alt="スクリーンショット 2020-04-21 23.13.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/c0cf9d54-9edb-0e79-26ba-1fd60fc47f06.png">
このとき主キーは「プロジェクト」と「課題ID」の組み合わせになり、このように**2つ以上のキーからなる主キーのことを複合主キー**と呼びます。

# 複合主キーによる結合
ここでもう一つ表を登場させます。
課題に対してどのようなアクションをとったかを管理するリストです。
<img width="410" alt="スクリーンショット 2020-04-21 23.26.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/7f064c71-c5af-573e-e144-68aadb29a5df.png">

この表を見れば、どの課題に対してどのような対応をしたかが分かります。
ただしこの表には「課題内容」がないので、必要であれば先ほどのリストを参照しなければいけません。つまりこういうことです。

<img width="487" alt="スクリーンショット 2020-04-21 23.32.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/4f07fd78-160b-fca1-54f2-c1974162db6d.png">

課題対応リストにある手がかり（＝外部キー）を使って、課題リストから必要な項目を参照し、取得することができます。

データベースの世界（SQL）では当然これができます。

```SQL:join.sql
SELECT *
FROM 課題リスト JOIN 課題対応リスト
ON 課題リスト.プロジェクト = 課題対応リスト.プロジェクト
AND 課題リスト.課題ID = 課題対応リスト.課題ID
```
いくつ結合のための項目が増えようが、ANDでつなげてしまえばOKです。
ただしPower BIでは、残念ながらこれができません。

# Power BIでの結合

Power BIでできるテーブルの結合は、1つのキーを使った結合のみです。
具体的にはこういう形です。

![結合.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/6fa160b4-c78d-4d33-1e88-941d4851b987.png)

上の例では2つのテーブルが1つのキーのペア「部門コード（所属部門コード）」を使って結合できています。

では2つのキーを使って結合しようとすると...そもそもできません。
<img width="917" alt="スクリーンショット 2020-04-22 0.03.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/910413af-7dfd-de97-ddda-004ef4129ab0.png">

# Power BIで複合主キーを扱う

### 考え方
解決策は、複合主キーを構成する複数項目を文字列連結するしかなさそうです。
事前にデータを加工する、ということです。
こうすれば、1つのキーで結合出来るようになります。
<img width="840" alt="スクリーンショット 2020-04-22 0.31.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/a720f741-0c2b-da05-d172-1943b5bb1b16.png">

もちろん、結合したいテーブルの数だけ同じ処理をする必要があります。
<img width="930" alt="スクリーンショット 2020-04-22 0.31.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/db1c4d4e-5e66-0ea5-999e-daf1d3d457f8.png">

### 操作手順
幸いPower BIにはPower Queryエディタという便利なツールがあるので、GUI操作で項目の文字列結合ができます。「列のマージ」を使います。


![列のマージ1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/d1fe5623-5e25-978d-810f-54bf1b1a38d2.png)

これで2つの主キーが連結されて、複合主キーからシンプルな主キーになりました。
![列のマージ1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/66dc8534-ee45-457e-6fb8-16f8fbc9e403.png)


ここまでの準備が完了すれば、あとは文字列連結した新しい主キーを使って、テーブル間を結合するだけです。

![結合2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/d83c5761-bb5b-6507-8513-f773bb4b4774.png)

### おまけ
文字列連結する前の元々の項目も重要な意味を持つ場合には、マスタテーブルを作っておくと便利そうです。
![列のマージ3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/1dd77688-7cf2-e624-7e27-106f82b04030.png)
これでマスタテーブルを結合しておけば、元のテーブルの項目「プロジェクト」や「課題ID」でスライサーを作ることもできるようになります。
![列のマージ4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/534cc0dc-5e5f-2bff-f62d-12d5555e94b9.png)

# 余談
複数テーブルを持つデータモデルを扱う場合、複合主キーはごくごく一般的であるため、Power BIで複合主キーによる結合ができないことは、個人的には意外でした。

Power Queryも確かに便利ですが、以下のような使い分けを意識しつつ、全てをPower BI側に寄せるのは避けた方が良いのかなと思います。

### Power BI側では特定の目的のためのデータ加工を行う
Power BIはあくまでData Martの位置付けとして、特定のユーザが特定の目的で実施するデータ加工を行う。データ加工はPower Queryを使いながら頑張る。

### 共通で利用されるデータ加工はData Warehouse側で実施
複数の部門やユーザが共通的に行うデータ加工をPower BI側で各自で行うと効率が悪い。多くの利用者が共通に実施するようなデータ処理は、主にIT部門が担当するData Warehouse側に寄せる。（Microsoft製品でいえばAzure Synapseなど）


とはいえ、そのデータ加工が「特定の目的」なのか「共通の目的」なのかは当初は分からないことが多そうです。なので、はじめはPower BI側で実装してみて、共通に利用されそうであれば（あるいはどこかのタイミングで棚卸しをして）Data Warehouse側に組み込む、という流れになるのかなと思います。