脱初心者！Tableauのクエリパイプライン（動作順序）を使いこなしたダッシュボード作成！

# はじめに

- Tableau初心者を脱して複雑なビューを作ろうとするとき、「全データを表示しているときは想定通りに動いていたのに、フィルターを使ったら計算結果が変わってしまった」とつまずくことがあります。私は何度もハマったのですが、**クエリパイプライン**を意識してダッシュボードを作るようになってから想定と違う動作になって戸惑うことが大きく減りました。

- 今回は、実際にTableauを動かしながらクエリパイプラインが計算結果にどう影響するかを理解してみます。特に、LOD表現は使いこなせるようになると表現できるビューの幅が広がり、さまざまな角度で分析できるダッシュボードが作成できます！

# そもそもクエリパイプラインとは

- Tableauがさまざまなアクション操作（フィルターや計算など）を実行する順序です。

- 公式ヘルプ「[Tableauの操作の順序](https://onlinehelp.tableau.com/current/pro/desktop/ja-jp/order_of_operations.html)」には次のように記載されています（図は日本語訳して転載）。

> Tableauの操作の順序は、クエリパイプラインとも呼ばれ、Tableauがさまざまなアクションを実行する順序です。（アクションは操作とも呼ばれます。）
> 多くの操作でフィルターが適用されます。つまり、ビューを構築してフィルターを追加すると、操作の順序で確立された順序で常にフィルターが実行されます。
> ユーザーが予測していたフィルターの実行順序と、操作の順序が指示する順序が異なる場合、予期しない結果になる可能性があります。
> Tableauの操作の順序には、次の図のすべての要素が含まれます。フィルターは青、他の操作（ほとんどは計算）は黒で示されます。
> ![image.png](https://qiita-image-store.s3.amazonaws.com/0/126976/b6eb81fc-f358-fc43-4a27-50c025e74e8c.png)

- はじめに触れた「フィルターを使ったら計算結果が変わってしまった」という問題は、「フィルター」と「計算」の順序が自分の想定と異なるために発生します。

- といっても、説明だけではイメージがわかないと思うので、さっそく実際に動かして計算結果がどのように変化するかを確かめてみます。動かしてみた結果は「[QueryPipelineExample | Tableau Public](https://public.tableau.com/profile/takaaki.koseki#!/vizhome/QueryPipelineExample/N)」にパブリッシュしてあるので、ぜひ実際に動かしながら確認してみてください。

# 実際に動かしてクエリパイプラインによる動作の違いを確認してみる

## 上位Nとフィルターの動作順序

|確認するクエリパイプライン（上から順に動作）|
|:--|
|コンテキストフィルター|
|上位N|
|ディメンションのフィルター|

**動かしてみた結果**
[QueryPipelineExample（上位Nとフィルターの動作順序） | Tableau Public](https://public.tableau.com/profile/takaaki.koseki#!/vizhome/QueryPipelineExample/N)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/126976/ed0c396b-063c-bc2e-e333-7ab18e97d287.png)

- 右上のグラフ：上位Nをディメンションでフィルター

  - 上位Nを**ディメンションでフィルター**すると、**フィルター前データ**の上位Nとなります。「クリップ」と「テーブル」にフィルターされていますが、総合ランキングの上位5名の顧客（左のグラフと同じ「石嶺」「山仲」「楯」「藤戸」「永瀬」）が表示されているのが確認できます。

- 右下のグラフ：上位Nをコンテキストフィルターでフィルター

  - 上位Nを**コンテキストフィルターでフィルター**すると、**フィルター後データ**の上位Nとなります。「クリップ」と「テーブル」にフィルターした結果、「クリップ」と「テーブル」でのランキング上位5名の顧客（左のグラフとは違い「宮田」「芝池」「西谷」「田所」「富松」）が表示されているのが確認できます。

- まとめ

  - 総合ランキングの上位Nを分析したいときは、ディメンションでフィルターします。

  - フィルターしたデータの上位Nを分析したいときは、コンテキストフィルターでフィルターします。

## FIXEDと表計算とフィルターの動作順序

|確認するクエリパイプライン（上から順に動作）|
|:--|
|FIXEDのLOD表現の計算|
|ディメンションのフィルター|
|表計算|

**動かしてみた結果**
[QueryPipelineExample（FIXEDと表計算とフィルターの動作順序） | Tableau Public](https://public.tableau.com/profile/takaaki.koseki#!/vizhome/QueryPipelineExample/FIXED)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/126976/0efff4f8-7883-3d6b-5202-62828dd8c891.png)

- 右上のグラフ：FIXEDのLOD表現を使用して割合を計算

  - **FIXED**の計算をディメンションでフィルターすると、**フィルター前**の合計に対する計算ができます。割合は`SUM([売上]) / SUM({ FIXED : SUM([売上]) })`で計算しています。「クリップ」と「コピー機」と「テーブル」にフィルターされていますが、サブカテゴリ全体での売上割合と同じ値（コピー機であれば左のグラフと同じ「13.09%」）が表示されているのが確認できます。

- 右下のグラフ：表計算を使用して割合を計算

  - **表計算**をディメンションでフィルターすると、**フィルター後**の合計に対する計算ができます。割合は`SUM([売上]) / TOTAL(SUM([売上]))`で計算しています。「クリップ」と「コピー機」と「テーブル」にフィルターした結果、「クリップ」と「コピー機」と「テーブル」で100%になる割合（コピー機であれば「65.29%」）が表示されているのが確認できます。

- まとめ

  - フィルター前の合計に対する分析をしたいときは、FIXEDで計算します。

  - フィルター後の合計に対する分析をしたいときは、表計算を使用します。

## INCLUDEとフィルターの動作順序

|確認するクエリパイプライン（上から順に動作）|
|:--|
|ディメンションのフィルター|
|INCLUDEのLOD表現の計算|
|メジャーのフィルター|

**動かしてみた結果**
[QueryPipelineExample（INCLUDEとフィルターの動作順序） | Tableau Public](https://public.tableau.com/profile/takaaki.koseki#!/vizhome/QueryPipelineExample/INCLUDE)
ディメンションのフィルター変更時
![image.png](https://qiita-image-store.s3.amazonaws.com/0/126976/41914dff-7e05-2522-cf18-a48e93b23575.png)

メジャーのフィルター変更時
![image.png](https://qiita-image-store.s3.amazonaws.com/0/126976/1a98117d-1b46-0763-17dd-0cb13b867fad.png)

- ディメンションのフィルター変更時の右のグラフ

  - **ディメンションのフィルター**は、INCLUDEの計算に**影響します**。平均値は`{ INCLUDE [都道府県]:SUM([売上]) }`で計算しています。「セカンドクラス」がフィルターで除外された結果、「セカンドクラス」以外のデータでの平均売上（関西地方であれば「6,395,100」）が表示されているのが確認できます。

- メジャーのフィルター変更時の右のグラフ

  - **メジャーのフィルター**はINCLUDEの計算に**影響しません**。こちらも平均値は`{ INCLUDE [都道府県]:SUM([売上]) }`です。「合計売上」でフィルターされていますが、地域全体での平均売上と同じ値（関西地方であれば左のグラフと同じ「8,128,757」）が表示されているのが確認できます。

- まとめ

  - INCLUDEの計算は、ディメンションのフィルターで変化します。

  - INCLUDEの計算は、メジャーのフィルターでは変化しません。

# クエリパイプラインを意識して一歩進んだダッシュボードを作ってみる

- いくつか実際に動かしながらクエリパイプラインによる動作の違いを確認してみましたが、使いこなすとさまざまな表現ができるようになります。ここでは2つ例を紹介します。

## フィルターを有効にしながら全体平均と比較する

**全体の平均との差を表示するサンプルダッシュボード**
[QueryPipelineExample（FIXED応用1） | Tableau Public](https://public.tableau.com/profile/takaaki.koseki#!/vizhome/QueryPipelineExample/FIXED1)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/126976/4683fae4-5f7a-ad72-a166-0ce39bf8c287.png)

- FIXEDを応用して、フィルターを使用しながら全体との差異を表示するビューが作成できます。サブカテゴリ別平均との差は`SUM({ FIXED : AVG({ FIXED [サブカテゴリ]: SUM([売上]) }) })`で計算しています。

## フィルターをAND条件のように使う

**フィルターで選択したすべてが対象となるデータを表示するサンプルダッシュボード**
[QueryPipelineExample（FIXED応用2） | Tableau Public](https://public.tableau.com/profile/takaaki.koseki#!/vizhome/QueryPipelineExample/FIXED2)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/126976/1d49279f-1e2b-cd01-0a46-4fdaf4dcfc30.png)

- こちらもFIXEDの応用で、フィルターの動きを「選択した**すべてが**対象」となるデータを表示する動きに変えることができます。サブカテゴリをコンテキストフィルターとし、`{ FIXED : COUNTD([サブカテゴリ])} = { FIXED [顧客名]: COUNTD([サブカテゴリ])}`が`TRUE`となるデータのみにフィルターをかけています。

- 通常のフィルターは「選択した**いずれか**が対象」となるデータを表示する動きなので、サンプルのように注釈を入れると親切です。

# おわりに

- Tableauは直感的な操作ですぐにビジュアライズができるのもよいところですが、使い込んでいくことでさらに表現が広がります。

- 今回のテーマであるクエリパイプラインを理解する以外にも、公開されているリソースの利用も表現を広げるとても良い方法だと思っています。例えば、公式ブログ「[Are you as Tableau-smart as a Tableau consultant? | Tableau Software](https://www.tableau.com/about/blog/2015/10/are-you-tableau-smart-tableau-consultant-45195)」では、「Challenge Workbook」と称していろいろな課題が紹介されています。公開から時間が経過しているため、最新バージョンでは設定ひとつでできるようになっているものもありますが、チャレンジしてみると新しい発見があって面白いと思います！