DAX/メジャーでリレーションシップを切り替える_エクセル

エクセル、パワーピボットで集計基準にしているリレーションシップを切り替える方法について試してみました。
一つのテーブルに複数の日付列があるので、その列基準のリレーションシップでそれぞれの集計をする。

# テーブルとリレーションシップ
- 使用するテーブルは以下です。
  - ディメンション：日付のテーブル
  - ファクト：作業履歴のテーブル
- 同じテーブルに対して、複数のリレーションシップをつける。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2383487/b5c17ffa-42ec-da34-6ecf-56825924b788.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2383487/3be7097a-7522-d492-2853-a4aeca7dcc40.png)

# 表示したいピボット
行ラベル：t作業[作業エリア]
列ラベル：Calendar[Date]
値の所には、この行列に当てはまる作業分類を表示したい。
その時に、開始日列、完了日列を使い分ける必要がある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2383487/27d5b9c9-5c4b-411f-30df-f911eb6e2b8a.png)

# DAX式
リレーションの状態
開始日列：アクティブ
完了日列：非アクティブ

文字列を表示するために、CONCATENATEXとVALUESを使います。
この場合は、行・列に当てはまるt作業'[作業分類]列で、重複は削除され、複数の場合は、カンマ区切りになります。
```:fx開始
=CONCATENATEX(VALUES('t作業'[作業分類]),'t作業'[作業分類],",")
```
```:fx完了
=CALCULATE(CONCATENATEX(VALUES('t作業'[作業分類]),'t作業'[作業分類],",")
,USERELATIONSHIP('t作業'[完了日],'Calendar'[Date]))
```

## USERELATIONSHIPの使い方
USERELATIONSHIPはとりあえず、CALCULATE関数のフィルター部分で指定するという方法なら使えそうです。
詳しくは以下リンク先と、DAXでの基本、CALCULATE関数について勉強しなおさないとですね。
- https://learn.microsoft.com/ja-jp/dax/userelationship-function-dax

## つくったDAXで表示
フィールドの設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2383487/0607e7ad-3c53-6912-85dd-2ae9682e76ed.png)

**開始日・完了日によって、リレーションの日別で集計できてる！**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2383487/0944ec1e-7f3f-1418-fa90-22d698b9d91d.png)

# 開始日・完了日をフィルターで切り替える
- パワークエリ編集から、新しく「空のクエリ」をつくる
- 以下を入れてテーブルをつくる
- このテーブルはリレーションしないでそのまま
```:t区分
let
    ソース = #table({"区分"}, {{"開始"}, {"完了"}}),
    変更された型 = Table.TransformColumnTypes(ソース,{{"区分", type text}})
in
    変更された型
```
切り替え用DAX
```:fx区分
=IF(
COUNTROWS(VALUES('t区分'[区分])) = 1,
SWITCH(
VALUES('t区分'[区分]),
"開始", 't作業'[fx開始],
"完了", 't作業'[fx完了]
)
)
```
フィールドの設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2383487/9c240bf4-c6a3-d45f-8b53-49fc100178b6.png)

**フィルターで切り替えられた！**
![リレーション切り替え.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2383487/b9a81139-7e2c-874b-0201-d67179c03961.gif)



# リレーションシップの切り替えを使わない方法
そもそも非アクティブなリレーションをつくって、切り替えるという事をしなくていいようにできないかやってみました。

## パワークエリで編集
日付列が二つあるので、難しくなってしまうのでこれを一つにします。

- パワークエリエディターで、t作業の「開始日」「完了日」を選択して、変換-列のピボット解除
- 以下のようになります
- 列名はいい感じに変えておく　属性⇒処理分類　値⇒日付

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2383487/dcbac789-9b2f-2b51-6d40-b4d5053109af.png)

```:エディター
let
    ソース = Excel.CurrentWorkbook(){[Name="t作業"]}[Content],
    変更された型 = Table.TransformColumnTypes(ソース,{{"作業分類", type text}, {"開始日", type datetime}, {"完了日", type datetime}, {"作業エリア", type text}}),
    ピボット解除された列 = Table.UnpivotOtherColumns(変更された型, {"作業エリア", "作業分類"}, "属性", "値"),
    #"名前が変更された列 " = Table.RenameColumns(ピボット解除された列,{{"属性", "処理分類"}, {"値", "日付"}})
in
    #"名前が変更された列 "
```

## リレーションシップとDAX
- t作業[日付]とCalendar[Date]でリレーションシップをつくる
- t作業テーブルに日付の列は一つだけなので、非アクティブなリレーションシップは必要なくなりました
- DAXをつくる
```:fx開始
=CALCULATE(CONCATENATEX(VALUES('t作業'[作業分類]),'t作業'[作業分類],","),
't作業'[処理分類]="開始日")
```
```:fx完了
=CALCULATE(CONCATENATEX(VALUES('t作業'[作業分類]),'t作業'[作業分類],","),
't作業'[処理分類]="完了日")
```
```:fx区分
=IF(
COUNTROWS(VALUES('t区分'[区分])) = 1,
SWITCH(
VALUES('t区分'[区分]),
"開始", 't作業'[fx開始],
"完了", 't作業'[fx完了]
)
)
```

## 完成したピボットテーブル
**最終的には、リレーションシップを切り替える場合と同じようにできました！**
どの方法がいいかは、その時々で検討する必要がありますね。
- 開始・完了を並べる場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2383487/d612a2e2-048a-392d-629b-ff3168448580.png)

- フィルターで切り替える場合
![一つの日付列.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2383487/8ade0f56-8f65-3a96-1706-706f69b6a51d.gif)


# 参考
- https://learn.microsoft.com/ja-jp/dax/calculate-function-dax
- https://learn.microsoft.com/ja-jp/power-bi/guidance/relationships-active-inactive
- https://modernexcel7.hatenablog.com/entry/2021/04/03/183436