URLパラメータによるダッシュボードのフィルタ仕様を理解する

# はじめに

Tableau Server, Tableau Cloudには、ダッシュボードのURL末尾にパラメータを付加することで、ダッシュボード表示時に同時にフィルタを行う機能があります。

【参考】[Tableauオンラインヘルプ　ビューURLの構築方法](https://help.tableau.com/current/pro/desktop/ja-jp/embed_structure.htm)

実際にこの機能を仕様する中で、「このフィルタってクエリパイプラインでいうどこにかかってるんだ？」と疑問になったので、いくつか検証を行ってみました。

## Tableauのクエリパイプライン

親の顔より見たクエリパイプラインの図
【出典】[Tableauオンラインヘルプ　Tableauの操作の順序](https://help.tableau.com/current/pro/desktop/ja-jp/embed_structure.htm)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/3b8a7b1c-f4a0-c27f-b994-246dae926030.png)

## 先に結論

URLパラメータによるフィルタが、上記のどのフィルタの扱いになるのかを確認したところ、以下のような特殊な振る舞いをするフィルタであることがわかりました。ややこしい。。。

URLで指定されたダッシュボード内の**全てのシートに、ディメンションフィルタまたはコンテキストフィルタの位置で**適用される

挙動を少し分解するとこんな感じです。

1. URLで指定されたダッシュボード内のシートにフィルタが入っているかどうかに関わらず、パラメータに指定したフィールド名がデータソースに存在するすべてのシートに適用される
1.  同一ワークブック内の他のダッシュボードには、URLで指定したダッシュボード内のフィルタで適用範囲として指定されている場合にのみ適用される
1.  フィルタの適用位置は、原則として「ディメンションフィルタ」の位置になる
1.  パラメータに指定したフィールド名がコンテキストフィルタとして設定されているシートに限り、「コンテキストフィルタ」の位置になる

この結論だけで十分やろって感じがしますが、念の為、実際のワークブック、ダッシュボードのスクリーンショットを使って、動きを確認していきたいと思います。

::: note warn
検証は以下の環境を前提として行っています。
* Tableau Cloud （2023.2）
* データソース：サンプルスーパーストア

異なる環境においては異なる動作をする可能性がありますが、本記事の執筆にあたっては他環境での検証を実施していない点ご了承ください。
:::

# フィルタの適用範囲を確認する

## 基本系：1ダッシュボード内における適用範囲を確認する
### シート内にフィルタがなくても適用される

まず基本系として、1ダッシュボード内におけるURLパラメータの適用範囲を確認します。
以下のような超シンプルなダッシュボードを用意しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/0970f7f8-d8f2-7f28-e524-088efd9c226c.png)

このダッシュボードには、売上BAN（バナー）と、カテゴリごとの棒グラフの２つのシートが配置されています。
そして、これらのシートにはディメンションフィルタは一切設定していません **（重要）**

このダッシュボードをTableau Cloud（以下TCL）にパブリッシュし、URLが以下のようになったとします。

`https://tableau-server-address/#/site/sitename/views/bookname/sheetname` 

このURLの末尾に、下記のようにURLパラメータとしてフィルタを付加してアクセスすると、、、

`https://tableau-server-address/#/site/sitename/views/bookname/sheetname?カテゴリ=家具` 

バナー、棒グラフともに家具にフィルタされた状態で表示されます。
（バナーは数字しか出ていませんが、値が小さくなっていることからフィルタされたと判断してください）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/506f8f66-4986-e805-4daa-196b0f772230.png)

ダッシュボードにも、シートにも一切フィルタは設定していませんが、どちらのシートもスーパーストアのデータソースを使っており、「カテゴリ」というフィールドがあるため、**URLパラメータにより両方のシートがフィルタされている**ことがわかります。
（結論　1.　の確認ができます）

### ダッシュボードの一部にだけ適用されるフィルタは正しく動作しない

上記の動きをもとに考えると、**ダッシュボードにフィルタを配置し、一部のシートにのみ適用される状態にしていても、URLパラメータを介してアクセスすると、本来フィルタを適用したくないシートにまで適用される**ことがわかります。

先ほどのダッシュボードを少し変更し、棒グラフだけに適用される「カテゴリ」のフィルタを配置してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/7dce74a8-30fb-4681-9c94-13abc06d3da9.png)

家具と事務用品にフィルタしたところ、売上バナーの値は変わらず、棒グラフだけフィルタされています。
このダッシュボードに対して、先ほどのようにURLパラメータを付与して下記のようにアクセスすると、、、

`https://tableau-server-address/#/site/sitename/views/bookname/sheetname?カテゴリ=家具` 

**売上バナーもきっちりフィルタされます**。これは結論1. の動作によるものだと想定されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/0c3d164d-6bc6-94bd-1bae-22ade3845abb.png)

:::note info
本例のダッシュボードのように、フィルタの適用範囲を一部のシートのみに設定したダッシュボードをURLパラメータによってフィルタできるようにする回避策については、本記事の末尾におまけとして記載しています
:::

## シート（タブ）を移動した際の動作を確認する

フィルタが全シートに問答無用にかかることから、「ひょっとしてデータソースフィルタとして動作するのでは？それならシートをタブで切り替えてもフィルタは維持されるよな」と思ったので、タブ移動を試してみることにします。

まず同じようなダッシュボードを２個用意します。

* 遷移元（一応フィルタ付き）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/107fdd89-8386-5c27-27ad-b87f52f31ff0.png)


* 遷移先
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/0b2e8ae4-d8d0-f588-e374-2ba1416f6512.png)


遷移先の棒グラフシートにも（表示してませんが）カテゴリのフィルタを入れておきました。

まず遷移元シートに対してURLパラメータ付きでアクセスすると、これまで見たように２シートともデータがフィルタされて表示されます。
`https://tableau-server-address/#/site/sitename/views/bookname/遷移元sheetname?カテゴリ=家具`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/c977ed65-a279-763e-72b2-7579808a5fe0.png)


この状態でダッシュボード上のタブで「４_TabDest」をクリックし移動してみると、、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/b3e36328-86da-a791-c5be-717f97c4af8d.png)


**フィルタは維持されていません。** フィルタを設定した棒グラフシートもダメです。なので、この時点でデータソースフィルタ説は崩壊です。
ということであとはコンテキストフィルタかディメンションフィルタか、くらいしか無くなりますが、これらはいずれも「フィルタの適用範囲」を指定することができるので、設定してみてURLパラメータによるフィルタでも機能が維持されるか確認してみます。

遷移元ダッシュボードのカテゴリフィルタの適用範囲を変更し、遷移先の棒グラフシートにも適用されるようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/2e2867dc-094a-bbcb-e54b-e419117faaee.png)


この状態で、遷移元シートにURLパラメータありでアクセスしたあと、「４_TabDest」をクリックし移動してみると、、、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/3996cb1e-57a7-9924-76b0-15b26eff48a6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/7df161e0-430d-80f3-726d-2e8cd173257c.png)

フィルタの適用範囲を拡張した棒グラフのシートにだけフィルタが引き継がれました。（結論2.の確認）
フィルタの動きとしてはコンテキストフィルタやディメンションフィルタに近そうです。

## LOD計算を使ってフィルタの適用位置を特定していく
### FIXED LOD計算
コンテキストフィルタであればFIXED LOD計算の前にかかるはず・・・！ということで、下記の表レベルLOD計算式を作成し、配置したダッシュボードを用意しました。

```
//全データの売上
{fixed:SUM([売上])}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/3299f1b5-cf65-3d81-7b0a-3318fd32db05.png)

カテゴリのフィルタは棒グラフシートに仕込んでおきました。（非表示）
このダッシュボードに対してこれまで同様URLパラメータ付きで、下記のようにアクセスすると、、

`https://tableau-server-address/#/site/sitename/views/bookname/sheetname?カテゴリ=家具`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/9892f2fb-bbeb-b6ab-f3f1-5bfcf5bd3f3b.png)



単純な売上合計はフィルタされているが、LOD計算側はフィルタされていません。よって、**URLパラメータがコンテキストフィルタとして機能していることはありません。**

では、明示的にコンテキストフィルタにしてみたらどうでしょうか。

先ほどのダッシュボードに設定されている棒グラフシート側のフィルタを、コンテキストフィルタに変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/9c0055cb-9370-0fb4-1e96-ee11859e3c4b.png)

その上で改めてURLパラメータ付きでアクセスすると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/06400a1e-bed0-40f8-c800-88bf1ed7f669.png)

棒グラフ側がFIXED LODの前にフィルタされました！！

というわけで、フィルタの適用位置は、
* **シートにフィルタが適用されていなかったり、ディメンションフィルタとして設定されていたら「ディメンションフィルタ」の位置で適用される（結論の3.）**
* **シートにコンテキストフィルタとして設定されていたら「コンテキストフィルタ」の位置で適用される（結論の4.）**

であることがわかりました。

### EXCLUDE LOD計算

もうここまででいいやろという気がしますが、ディメンションフィルタと見せかけてもっと後でかかってたりしないよね？という疑念をはらすために一応やっておきましょう。EXCLUDE LOD計算を使ったフィールドを配置したシートを用意し、URLパラメータでフィルタされればディメンションフィルタの位置で確定です。

```
//カテゴリを除外した売上合計
{EXCLUDE [カテゴリ]:SUM([売上])}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/64475636-348c-e9cf-1e42-d99721ca8281.png)

こじのダッシュボードに対し、いつも通りURLパラメータありでアクセスします。
`https://tableau-server-address/#/site/sitename/views/bookname/sheetname?カテゴリ=家具`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/8f97b9f6-54a4-3dd0-1364-b782ab2f6931.png)

想定通りEXCLUDE LOD計算側もフィルタされました。これにて　**「フィルタ適用位置は、明示的にコンテキストフィルタにしない限りディメンションフィルタの位置」**　で確定です。

え？メジャー項目をURLパラメータに使ったらメジャーフィルタの位置でかかるのか、って？　
それは試してないなぁ。。。（すっとぼけ）
業務でよく使うケースは、ディメンション項目をURLパラメータでフィルタする、ということで割愛しました。ご了承ください。

# （おまけ）URLパラメータを使って、ダッシュボード内の一部のシートだけフィルタしたいときはどうする？

これまで見てきた通り、URLパラメータによるフィルタでは、ダッシュボード内の各シートにフィルタが設定されているかどうかに関わらず、パラメータと同じ名称のフィールドがデータソースに存在すればフィルタが適用される仕様でした。

逆に考えると、「フィルタを適用したいシートで使っているデータソースと同じ名前のフィールドが、適用したくないシートに無ければよい」ということになります。
そう、**データソースを複製してフィールド名をリネームする**作戦で実現できそうです。

## やりたきこと
下記のように、棒グラフだけにカテゴリフィルタが適用されているダッシュボードに対して、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/1d0b07de-f3ba-1a19-def0-68d310442b1a.png)


URLパラメータ付きでいつものようにアクセスすると、フィルタが適用されている棒グラフのシートだけフィルタされるようにしたい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/edcbfebe-6830-3cd7-770e-db1e8962ad8b.png)

## 実現手順

**1. １つ目のデータソースを使って、売上バナーのシートを作成する**
普通にシートを作るだけなので、ポイントも何もありません。

**2. 同じスーパーストアに接続する別のデータソースを新たに作成し、「カテゴリ」のフィールド名をリネームする**
同じデータに接続しますが、棒グラフシート用のデータとしてもう一つデータソースを用意します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/ae1f0893-31cf-a5c1-59b3-b0b35d52f863.png)



そして、フィルタを適用したい棒グラフ用シートをこちらのデータソースを使って作成しますが、その際、フィルタに使用するフィールド名を変更し、（フィルタを適用したくない）売上バナー側で使ったデータソースには存在しない名前にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/66af4009-269f-36c3-a3cf-144350b2d5bd.png)

これで、
* 1つ目のデータソース（バナーで使用）：「カテゴリ」というフィールドはあるが、「カテゴリ2」というフィールドはない
* 2つ目のデータソース（棒グラフで使用）：「カテゴリ」というフィールドはないが、「カテゴリ2」というフィールドはある
という状態を作ることができました。

**3.ダッシュボードを作って、「カテゴリ2」をURLパラメータに」指定してフィルタする**

２つのシートを組み合わせてダッシュボードとし、パブリッシュします。（ダッシュボードのフィルタに「２」と出ていると微妙なので、フィルタのタイトルは「カテゴリ」に戻しておきました。）
そのあといつものURLパラメータを使ってアクセスするのですが、その際パラメータに指定するのは、リネームした方の「カテゴリ２」にします。

`https://tableau-server-address/#/site/sitename/views/bookname/sheetname?カテゴリ２=家具`

「カテゴリ2」は売上バナー側のデータソースに存在しませんから、当初の目論見通り、棒グラフだけにURLパラメータを適用させることができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945012/78f5f4b7-89ff-d89b-9292-b66650eff860.png)

# おわりに
どこに需要があるんだって内容ですが、どこかに同じ疑問を持つ人がいると信じて・・・
でも記事内容はクエリパイプラインの復習にはなるかな。