keyboard_arrow_up
ホームツール

Tableauにおけるリレーションシップ...

Tableauにおけるリレーションシップとは

こんにちは、minoRiです。私は現在、Tableauを活用できるようになるために、日々学習をしています。

前にTableau Certified Data Analystに合格し、実践的なデータ分析をやってみようとすると、「データ結合」のあたりで躓いたため、関連機能について再度学習をしました。

前回は「結合」機能について、定義、種類、実践例を図解を用いてまとめました。

今回は関連機能である「リレーションシップ(関係)」について、どんな操作か、実践例を用いて解説していきます。

文章で説明されるだけでは理解が難しい部分もあると思い、手元で操作ができるようにし、図解しました。1つずつ確認しながら「なぜそうなるのか?」を一緒に紐解いていきましょう。

※記事で利用するサンプルデータのダウンロードリンク

下記リンクは、この記事内で扱うECショップのサンプルデータ(ChatGPTで作成)のダウンロードリンクです。理解を深めるためにも、自分の手元で同じ操作をしながら読み進めることをおすすめします。

サンプルデータのダウンロードリンク


リレーションシップとは?

定義と推奨理由

テーブル(表)同士を共通項目=一致するフィールド(データ結合でいう結合句)を使ってうまく結びつけてくれる仕組みのことです。

「関係」とも呼ばれるTableauの機能です。

リレーションシップは次のような特徴を持つため、Tableauの公式ドキュメントでは結合よりもリレーションシップの利用を推奨しています。

  • 自動で最適化される:リレーションシップでは、結合タイプをあらかじめ指定する必要はなく、必要なフィールドを関係として設定するだけです。ワークシートで使用しているカラムに基づき、Tableau が適切な結びつけ方を自動的に選択し、分析に必要なクエリを生成します。

  • 異なる粒度も安全に扱える:結びつけた2つのテーブルは 1 つの結合テーブルにはならず、それぞれのテーブルの元の粒度が維持されます。これにより、異なる粒度・異なる役割のテーブルを同じデータソース内で扱っても、粒度のズレや意図しない集計の崩れを起こしにくくなります。(「粒度」…データ1 行がどのくらい細かい単位を表しているか)

  • 効率的で扱いやすい:リレーションシップでは、そのビューに関係するテーブルのみに対してクエリが実行されるため、分析に不要なデータまで事前に固定した結合として扱う必要が減ります。結果として、パフォーマンスの確保と、運用しやすいデータモデルの両立がしやすくなる場合があります。

  • リスク軽減:Tableau は、現在のビューで使用されているフィールドとリレーションシップ定義に応じてクエリを生成します。そのため、不適切な結合設定によるメジャー値の欠落や、結合で発生しがちな現実には発生していないデータを作り出すといった問題を設定次第で防ぎやすくなります。

  • 柔軟な拡張性:単一のデータソースでさまざまな詳細レベルの複数テーブルが使用でき、表同士の関係性を明示したまま管理できます。ビジュアライゼーションのフィールドとフィルターに基づいて必要なテーブルのみがクエリされるため、さまざまな分析フローに使用できるデータ ソースを構築できます。

「うまく」と書いた理由は、適切にリレーションシップを活用できれば、1行対複数行や複数行対複数行の結びつけの場合にも、現実には発生していないデータを作り出すこと(行の複製による集計値の水増し)を起こりにくくできるためです。詳細については、この後の具体例で触れます

「結びつけ」と表現したのは、実際にはテーブルは独立したままで、データの粒度などはそれぞれ維持されるからです。

言葉だけで定義を書かれても、私には難しかったので、具体例を用いて解説します。

具体例

【ECショップの顧客情報と注文情報を結びつけて、居住市別の平均売上額を出したい場合】

①”customer”テーブル”と②“sales(1-3月)”テーブルを用意します。

”customer”テーブルのデータ
“sales(1-3月)”テーブルのデータ

一致するフィールドとなる「顧客ID」で”customer”テーブルと“sales(1-3月)”テーブルのデータを結びつけます。

この時やっていることを図で表現すると…

一致するフィールドである「顧客ID」の「C002」に該当するデータだけを見ると”customer”テーブルには1行、“sales(1-3月)”テーブルには3行あります。“sales(1-3月)”テーブルの3行は1つのグループと認識し、”customer”にある1行と結びつけます。これを各顧客IDで行います。

”customer”テーブルと“sales(1-3月)”テーブルをリレーションシップで結びつけるイメージ図

このように1行:1グループのような、1対多で結びつけられる場合にリレーションシップは効果的で、現実には発生していないデータを作り出してしまうことを防ぎやすいです。

【同じデータで結合をした場合】

1行のデータに対応する複数行のデータ全てが結びつきます。そのまま集計をすると、行が複製されていることにより集計値が水増しされた値となります。これが、現実には発生していないデータを作り出してしまう、ということです。

”customer”テーブルと“sales(1-3月)”テーブルを内部結合した時の表

リレーションシップは、テーブル自体を結びつけて1つのテーブルを作るわけではないので、データソースページなどでは別々のテーブルとして表示されます。

以上がTableauにおける「リレーションシップ」という操作です。

つまりリレーションシップとは、「テーブル同士を一致するフィールドを使ってうまく結びつけてくれる仕組み」のことです。

今回の例で言うと、“sales(1-3月)”テーブルと”customer”テーブルを「顧客ID」で結びつけています。”customer”テーブルの1行と“sales(1-3月)”テーブルの3行を1つのグループとみなし、1行:1グループで結びつけられ、現実には発生していないデータを作り出すことなく、データを結びつけられます。「うまく」と表現したのは、このためです。

居住市別の平均売上額を出す場合、シート作成画面で「居住市」を行に、メジャーバリューをマークカードのテキストに置き、集計方法を平均に設定することで求めることができます。

居住市別の平均売上額を出したときの表

リレーションシップ機能を使う前のポイント

「リレーションシップを設定する前には、必ずデータの中身を確認すること」をおすすめします。

リレーションシップの集計結果は「一致するフィールドの合致状況・重複状況・テーブルの粒度」の3点が影響しやすいですが、これらを確かめる際、自分の目でサンプル行を直接確認するとが気づきやすいためおすすめです。

事前にデータの状態を把握しておけば、キーの不一致や粒度の違いによる影響を見越して設計することができます。

リレーションシップをする前にデータの中身を確認する際は、以下の点に注意しましょう。

  • 一致するフィールドの合致性

  • データ型が同じか(文字列と数値の混在がないか)

  • 表記揺れ(例:「001」と「1」)や全角半角の混在がないか

  • 一致するフィールドの重複状況

  • 一致するフィールドの値が各テーブルで一意か、それとも同じ値が複数行あるか(=1対1/1対多/多対多のどの関係になるか)を事前に把握する

  • 一致するフィールドの欠損(NULL)

  • 欠損がある場合はNULL表示が増える可能性がある

  • テーブルの粒度

  • 1行が何を表しているのか(顧客単位、注文単位、明細単位など)

もし、このような確認をしないままリレーションシップ機能を使うと、狙ったデータ集計や分析ができない場合があります。この後の実践例でも、その動きについて触れるため、データの中身を確認しながら進めましょう。


リレーションシップ実践例

私が勉強した時と同じ手順でTableau Publicを使って解説していきます。みなさんも実際に自分の手でデータがどうなっているかを確認しながらやってみることをおすすめします。

この後のセクションでも、冒頭のサンプルデータを使って解説を進めます。使うテーブルは、それぞれのセクションで確認します。

リレーションシップ①マスタデータ×マスタデータの場合

(※マスタデータとは、システムの基準となるデータ。)

”customer”テーブルと”loyalty”テーブルを使います。データの中身をExcelやTableauで確認したうえで、リレーションシップの操作に進んでください。

今回は、居住市別の年齢・保有ポイントの平均値を出すことを目的に進めていきます。

2つのテーブルを共通項目「顧客ID」を一致するフィールドにしてリレーションシップで結びつけます。結果は以下の画像のようになります(どちらのテーブルを選択しているか、で表の表示内容が変わります)。

”customer”テーブルと”loyalty”テーブルを「顧客ID」でリレーションシップをした結果の画面

シート作成の画面に移って、表を作っていきます。居住市別に年齢と保有ポイントの平均を出すために、以下の操作をしましょう。

  1. 「居住市」を行に、「メジャーネーム」を列に配置

  2. 「メジャーバリュー」をマークカードのテキストに配置

  3. 「年齢」「保有ポイント」は平均で集計

  4. アナリティクスタブから、列の総計を追加して表示

完成した表と併せて、事前に計算しておいた平均年齢・平均保有ポイントを以下の画像に示しています。これは今回の練習にあたって、Tableauで集計した値が想定どおりかを検算するためのものです。

”customer”テーブルと”loyalty”テーブルを「顧客ID」でリレーションシップをして作ったテキスト表

表の値と事前に計算しておいた値を比べると、東京・大阪・総計の平均年齢・平均保有ポイントは、事前に計算しておいた値と一致する正しい集計値であることがわかります。今回は確認のために、先に集計値を計算しておきました。

今回のマスタ×マスタのリレーションシップの結果は、集計値は想定していた値となっており、すべてが1対1で対応しています。

「すべてが1対1で対応」とは、どういうことかについて次に解説していきます。

図解

2つのテーブルの中で、一致するフィールド「顧客ID」が「C001」の行を見てみましょう。

”customer”テーブルに1行、”loyalty”テーブルにも1行のデータがあります。この時、”customer”テーブルの「C001」の1行が、”loyalty”テーブルの「C001」の1行と対応し結びつきます。

顧客ID「C001」だけで見て”customer”テーブルと”loyalty”テーブルをリレーションシップで結びつけるイメージ図

このような動きが各「顧客ID」で行われており、”customer”テーブルと”loyalty”テーブルは「1行ずつ1対1で対応している」と言えます。

そして、年齢や保有ポイントは想定していた値となります。

【同じデータで結合した場合】

同じデータを使って内部結合し、列や行などにも同じ配置でカラムを入れてみます。結果は、以下の画像の通りになります。

”customer”テーブルと”loyalty”テーブルを「顧客ID」で内部結合して作った表

この場合にも1対1で対応し、集計値も想定していた値になります。

しかし、「リレーションシップとは?」のセクションで書いた特徴があり、次からのセクションで結果に結合との差が出るため、結合よりリレーションシップが推奨されています。

【マスタデータ×マスタデータの場合のまとめ】

マスタデータ×マスタデータでリレーションシップをした場合、1つの一致するフィールドを基準に1対1でデータが結びつけられます。

今回リレーションシップで使用したのと同じデータで内部結合した場合、集計値や1対1で対応する点は同じです。しかし、Tableau公式では結合よりリレーションシップが推奨されています。

リレーションシップ②ログデータ×マスタデータの場合

(※ログデータとは、1件のイベントを1行として時系列で記録されるデータ。)

マスタデータではないものとリレーションシップで結びつけると、どうなるのでしょうか。

”sales(1-3月)”テーブルと”customer”テーブルを使います。データの中身をExcelやTableauで確認したうえで、リレーションシップの操作に進んでください。

今回は、会員の居住市別に売上金額と年齢の平均値を出すことを目的として進めていきましょう。

2つのテーブルを共通項目「顧客ID」を一致するフィールドにしてリレーションシップで結びつけます。結果は以下の画像のようになります(どちらのテーブルを選択しているか、で表の表示内容が変わります)。

”sales(1-3月)”テーブルと”customer”テーブルを「顧客ID」でリレーションシップをした結果の画面

シート作成の画面に移って、表を作っていきます。居住市別で売上金額と年齢の平均値を出すために、以下の操作をしましょう。

  1. 「居住市」を行に、「メジャーネーム」を列に配置

  2. 「メジャーバリュー」をマークカードのテキストに配置

  3. 売上金額と年齢は平均をセット

  4. アナリティクスタブから、列の総計を追加して表示

完成した表と併せて、事前に計算しておいた検算用の各値を画像に示しています。

”sales(1-3月)”テーブルと”customer”テーブルを「顧客ID」でリレーションシップをして作ったテキスト表

表の値と事前に計算しておいた値を比べると、東京・大阪・総計の平均売上金額・平均年齢は、事前に計算しておいた値と一致する正しい集計値であることがわかります。

今回のログ×マスタのリレーションシップの結果は、集計値は想定していた値となっており、すべてが1対多で対応しています。

「すべてが1対多で対応」とは、どういうことかについて次に解説していきます。

図解

2つのテーブルの中で、一致するフィールド「顧客ID」が「C002」の部分を見てみましょう。”customer”テーブルには1行、”sales(1-3月)”テーブルに3行のデータがあり、1行:3行(1グループ)のように1対多で結びつきます。

顧客ID「C002」だけで見て”sales(1-3月)”テーブルと”customer”テーブルをリレーションシップで結びつけるイメージ図

先ほど作った表の行に「注文ID」を追加すると、1人の顧客が複数回注文している場合に、”customer”テーブル(マスタデータ)に入っている年齢の値が全ての行で当てはめられています。

先ほど作った”sales(1-3月)”テーブルと”customer”テーブルの表に注文IDを追加した表

しかし、作成した表の集計値は想定していた値となっている=年齢が複数回表示されていても、それを1人分として計算をした、ということです。

これは、表にした時に「マスタデータの値が繰り返し表示されて見える」だけで、実際にマスタデータの値がデータ内部で複製されているわけではありません。あくまで「どのログデータとどのマスタデータが結びつくか」を見せるために、繰り返し表示してくれているイメージです。

今回の例のように年齢が繰り返し表示されても、リレーションシップはテーブルを結合しないため「元データが複製された」ことを意味しません。多くの場合、集計結果はビューの詳細レベル(どのディメンションを置くか)と集計方法に影響されます。

内部的にはマスタデータとログデータの粒度や構造は保持されており、分析に使う時にはテーブルごとに想定どおりの集計がされます。

【同じデータで結合した場合】

同じデータで内部結合を行った場合には、現実には発生していないデータを作り出してしまい、マスタデータの行が複製され、値が水増しされます。

”sales(1-3月)”テーブルと”customer”テーブルを「顧客ID」で内部結合して作った表

「現実には発生していないデータを作り出す」と言うのは、先ほど書いた「マスタデータの値が繰り返し表示される」というものです。結合はこの時、ログデータに合わせてマスタデータを複製して表示し、見えるままに集計を行います。よって、同じ顧客の年齢を表示された回数分すべて集計することで、値に水増しが起こります。

リレーションシップを利用すれば、この現象を防ぐことができるのです。

【ログデータ×マスタデータの場合のまとめ】

ログデータ×マスタデータでリレーションシップした場合、1つの一致するフィールドを基準にマスターデータの1行とログデータの一括りとなるデータが結びつけられます。

1対多で対応しており、集計値も想定通りの値となりました。

ログデータの粒度でテキスト表を作った場合には、マスタデータ側の値が繰り返し表示されるが、これは見かけ上の表現で、集計には影響しません。

今回リレーションシップで使用したのと同じデータで内部結合した場合、現実には発生していないデータを作り出してしまい、集計値も想定していた値にはなりませんでした。

ログデータとマスタデータを合わせてデータ分析をしたい場合は、リレーションシップ機能を利用しましょう。

リレーションシップ③ログデータ×ログデータの場合

次に、ログデータ同士のリレーションシップではどうなるでしょうか。

”sales(1-3月)”テーブルと”buyback(1-3月)”テーブルを使います。データの中身をExcelやTableauで確認したうえで、リレーションシップの操作に進んでください。

今回は、月・カテゴリー・商品状態で分類された売上金額・買取金額の表を作ることを目的として進めていきましょう。

2つのテーブルを共通項目「月・カテゴリー・商品状態」の3つを一致するフィールドにしてリレーションシップで結びつけます。結果は以下の画像のようになります(どちらのテーブルを選択しているか、で表の表示内容が変わります)。

”sales(1-3月)”テーブルと”buyback(1-3月)”テーブルを「月・カテゴリー・商品状態」でリレーションシップをした結果の画面

シート作成の画面に移って、表を作っていきます。売上・買取金額の表を作るために、以下の操作をしましょう。

  1. 「月・カテゴリー・商品状態」の3つを行に、「メジャーネーム」を列に配置

  2. 「メジャーバリュー」をマークカードのテキストに配置

  3. アナリティクスタブから、列の総計を追加して表示

完成した表と併せて、事前に計算しておいた検算用の各値を画像に示しています。

”sales(1-3月)”テーブルと”buyback(1-3月)”テーブルを「月・カテゴリー・商品状態」でリレーションシップをして作ったテキスト表

表の値と事前に計算しておいた値を比べると、事前に計算しておいた値と一致する正しい集計値であることがわかります。

今回のログ×ログのリレーションシップの結果は、集計値は想定していた値となっており、すべて多対多で対応しています。

「すべて多対多で対応」とは、どういうことかについて次に解説していきます。

図解

2つのテーブルの中で、一致するフィールド「1月」「新品」「洋服」の全てを満たす部分を見てみましょう。”sales(1-3月)”テーブルには5行、”buyback(1-3月)”テーブルにも5行のデータがあり、複数(1グループ):複数(1グループ)のように多対多で結びつきます。

「1月」「新品」「洋服」だけで見て”sales(1-3月)”テーブルと”buyback(1-3月)”テーブルをリレーションシップで結びつけるイメージ図

先ほど作った表の行に”sales(1-3月)”テーブルの「注文ID」を追加すると、売上の明細行が増えます。一月に同じカテゴリ・商品状態の注文がある場合に、”buyback(1-3月)”テーブルの同じ月・カテゴリ・商品状態の集計された値が、繰り返し表示されます。

先ほど作った”sales(1-3月)”テーブルと”buyback(1-3月)”テーブルの表に「注文ID」を追加した表

しかし、作成した表の集計値は想定していた値となっている=買取金額が複数回表示されていても同じ月・カテゴリー・商品状態の1括りとして計算をした、ということです。

ログデータ×マスタデータの時と同じように、表にした時に「”sales(1-3月)”テーブルの値が繰り返し表示されて見える」だけで、実際に”sales(1-3月)”テーブルの値が複製されているわけではありません。あくまで「”sales(1-3月)”テーブルのどのデータと”buyback(1-3月)”テーブルのどのデータが結びつくか」を見せているイメージです。

内部的にはデータの粒度や構造は保持されており、分析に使う時にはテーブルごとに想定どおりに集計されます。

【同じデータで結合した場合】

同じデータで内部結合を行った場合には、現実には発生していないデータを作り出してしまい、データの行が複製され、以下の画像のように値が水増しされます。

”sales(1-3月)”テーブルと”buyback(1-3月)”テーブルを「月・カテゴリー・商品状態」で内部結合して作った表

ここもログデータ×マスタデータの場合で言ったのと同じように、ログデータに合わせてもう1つのログデータを複製して表示し、見えるままに集計を行います。今回は合計値を出しているので、水増しが先ほどより大きく反映されています。

【ディメンションを入れ替える】

リレーションシップでデータを結びつけた場合は、各メジャーの集計値は想定していた値となりました。

先ほど作った表の行に”sales(1-3月)”テーブルの「注文ID」を追加すると、売上金額の詳細は見ることができます。この時、買取金額の値には「月」「カテゴリー」「商品状態」で分類した時の合計値が当てはめられています。

最初に作った”sales(1-3月)”テーブルと”buyback(1-3月)”テーブルの表に「注文ID」を追加した表

このシートを複製して、行に入れている”sales(1-3月)”テーブルの「注文ID」を”buyback(1-3月)”テーブルの「買取ID」と入れ替えてみましょう。

最初に作った”sales(1-3月)”テーブルと”buyback(1-3月)”テーブルの表のディメンションを入れ替えた表

今度は買取金額の詳細を見ることができるようになり、”sales(1-3月)”テーブルの「月」「カテゴリー」「商品状態」で分類した時の売上金額の合計値が当てはめられています。

このようなことが起こる理由としては、リレーションシップでは「シート内で使ったデータがあるテーブル」に応じて表が作られるためです。よって、どちらのテーブルの項目を軸にするかで表示結果が変わります。

【売上金額と買取金額の差額を計算で出してみよう】

同じデータのまま、売上金額と買取金額の差額を計算式を作って出してみましょう。

「計算フィールドの作成」から、以下の計算式を作ります。

 [売上金額]- [買取金額]

想定とは違う計算結果となりました。

最初に作った表に[売上金額]- [買取金額]の計算結果を入れた表

次に、また新しく「計算フィールドの作成」をして、以下の計算式を作ります。

SUM([売上金額]) - SUM([買取金額])

今度は、想定通りの計算結果となりました。

最初に作った表にSUM([売上金額]) - SUM([買取金額])の計算結果を入れた表

なぜSUMをつける・つけないでこのような計算結果の違いが出るのでしょうか?前者の計算式は、どのような計算をした結果なのでしょうか?解説していきます。

「1月」「洋服」「新品」の両テーブルのデータを見ると、”sales(1-3月)”テーブルに5行、”buyback(1-3月)”テーブルにも5行のデータがあります。これで1つのデータに対して5通りの計算がされ、5行分それが行われます。5行×5行=25通りとなる全ての組み合わせで計算フィールドに設定した計算が行われ、その合計値が計算結果として出ています。

[売上金額]- [買取金額]の時の計算で起こっていることの図

“ [売上金額]- [買取金額] ”、“ SUM([売上金額]) - SUM([買取金額]) ”どちらの計算式も2つのテーブルをまたいで行われます。

前者は、[売上金額1行]‐[買取金額1行]のような計算になるため、一致するフィールドを基準に各組み合せでの計算の和を出しています。

後者のSUM([売上金額]) - SUM([買取金額])は、”sales(1-3月)”テーブルと”buyback(1-3月)”テーブルのそれぞれのテーブル内で合計した結果の差を出しています。

2つのデータを使って計算フィールドを作る際は、使うデータがテーブルをまたいでいるかどうか、を考慮して計算式を作る必要があります。

【リレーションシップを利用したデータの計算式を作るポイント】

  • 1つのテーブルの中で集計値を出すときは、そのテーブル内だけで集計する

  • その後で別のテーブルと組み合わせる場合は、それぞれの集計結果をつなぎ合わせる

  • データテーブルをまたがって1行ごとの計算をする場合は、キーで関連づけられる範囲内の行をすべて組み合わせて計算する

今回の場合は、売上金額と買取金額の差額を出したかったので、売上金額合計と買取金額合計の差を求める式になります。したがって、売上金額と買取金額の集計値を出してから、別テーブルと組み合わせることになります。つまり、SUM([売上金額]) - SUM([買取金額])という式が適している、ということです。

【ログデータ×ログデータの場合のまとめ】

ログデータ×ログデータでリレーションシップをした場合、一致するフィールドを基準にログデータの一括りとなるデータ同士が結びつけられます。

多対多で対応しており、集計値も想定通りの値となりました。

同じデータで結合した場合:現実には発生していないデータを作り出していました(行がかけ算式に複製され、値が水増しされる)。

リレーションシップでは、シートに使ったデータがあるテーブルに応じて表が作られていました。よって、どちらのテーブルのカラムを軸として入れるかで表示結果が変わります。

計算式を作る場合は、テーブルをまたいでいるかどうか、どのタイミングでテーブルをまたぐのかを考慮した上で計算式を作成する必要があります。

リレーションシップ④ログデータ×ログデータ(欠損値あり)の場合

※ここでの欠損は、特定の組み合わせ行が存在しないことを指します。

最後に、データに欠損があるもの同士でのリレーションシップはどうなるでしょうか。

”sales(4-6月)”テーブルと”buyback(4-6月)”テーブルを使います。データの中身をExcelやTableauで確認したうえで、リレーションシップの操作に進んでください。

ちなみに、データはそれぞれ以下の部分が欠損しています。

  • ”sales(4-6月)”テーブル:5月の中古の洋服、6月の新品のアクセサリー

  • ”buyback(4-6月)”テーブル:5月の新品のアクセサリー、6月の中古の洋服

今回は、月・カテゴリー・商品状態で分類された売上金額・買取金額の合計を出すことを目的として進めていきましょう。

2つのテーブルを共通項目「月・カテゴリー・商品状態」の3つを一致するフィールドにしてリレーションシップで結びつけます。結果は以下の画像のようになります(どちらのテーブルを選択しているか、で表の表示内容が変わります)。

”sales(4-6月)”テーブルと”buyback(4-6月)”テーブルを「月・カテゴリー・商品状態」でリレーションシップをした結果の画面

シート作成の画面に移って、表を作っていきます。売上・買取額の合計値を出すために、以下の操作をしましょう。

  1. 「月・カテゴリー・商品状態」の3つを行に、「メジャーネーム」を列に配置

  2. 「メジャーバリュー」をマークカードのテキストに配置

  3. アナリティクスタブから、列の総計を追加して表示

完成した表と併せて、事前に計算しておいた検算用の各値を画像に示しています。

”sales(4-6月)”テーブルと”buyback(4-6月)”テーブルを「月・カテゴリー・商品状態」でリレーションシップをして作ったテキスト表

表の値と事前に計算しておいた値を比べると、事前に計算していた値と一致する正しい集計値であることがわかります。

今回のログ×ログ(欠損値あり)のリレーションシップの結果は、集計値は想定していた値となっており、すべて多対多で対応しています。

欠損値があるのに「すべて多対多で対応」とは、どういうことかについて次に解説していきます。

図解

2つのテーブルの中で、一致するフィールド「月・カテゴリー・商品状態」が「4月・洋服・新品」の部分を見てみましょう。”sales(4-6月)”テーブルには5行、”buyback(4-6月)”テーブルにも5行のデータがあり、複数(1グループ):複数(1グループ)のように多対多で結びつきます。

欠損部分で起きていることを、一致するフィールド「月・カテゴリー・商品状態」が「5月・アクセサリー・新品」の部分を見てみましょう。”sales(4-6月)”テーブルには5行、”buyback(4-6月)”テーブルにはデータがないため、”sales(4-6月)”テーブルとは何も結びつきません。

「5月・アクセサリー・新品」だけで見て”sales(4-6月)”テーブルと”buyback(4-6月)”テーブルをリレーションシップで結びつける欠損部分のイメージ図

しかし、表を作った時には、”sales(4-6月)”テーブルのディメンションを行に入れたため、そのデータに応じて表を作ることになります。そのため、”buyback(4-6月)”テーブルにしか存在しない組み合わせのデータは、”sales(4-6月)”テーブルのデータに応じた表ではNULLの行として見えます。

「リレーションシップ③ログデータ×ログデータ」中【ディメンションを入れ替える】のセクションで書いたように、どちらのデータをシートに使うかに応じてテーブルが変わるため、”buyback(4-6月)”テーブルのデータをシートに使うと、表の中の欠損位置は変わります。

逆に、”sales(4-6月)”テーブルにデータがなく、”buyback(4-6月)”テーブルに5行ある場合でも同じことが起きています。

【同じデータで結合した場合】

同じデータで内部結合をした場合には、欠損部分と対応するはずだったデータが除外されます。また、現実には発生していないデータを作り出す(行がかけ算式に複製され、値が水増しされる)ことにもつながります。

”sales(4-6月)”テーブルと”buyback(4-6月)”テーブルを「月・カテゴリー・商品状態」で内部結合して作った表

同じデータで左結合をした場合には、左に設定したテーブルデータは全て残り、右に設定したテーブルのうち、左で欠損していることで結合されなかったデータは除外されます。右結合にした場合は、逆の状態になります。また、どちらの場合も現実には発生していないデータを作り出され、行が複製されるため、値は水増しされます。

”sales(4-6月)”テーブルと”buyback(4-6月)”テーブルを「月・カテゴリー・商品状態」で左結合して作った表

同じデータで完全外部結合をした場合には、左右に設定したどちらのテーブルのデータも残り、リレーションシップ機能を使った場合とデータの表示位置は同じになります。シートで使うデータn同じです。しかし、現実には発生していないデータを作り出され、行が複製されるため、値は水増しされます。

”sales(4-6月)”テーブルと”buyback(4-6月)”テーブルを「月・カテゴリー・商品状態」で完全外部結合して作った表

【NULLについて】

リレーションシップでデータを結びつけた場合の、各メジャーの集計値は想定していた値となりますが、リレーションシップ③の時とは違う部分があります。

”sales(4-6月)”テーブルになかった欠損部分が行ごと表示されておらず、そこと結びつくはずだった”buyback(4-6月)”テーブルの値がNULLの行に集計されています。

NULLや空欄をなくした表を作りたい場合、先ほどの表から考えるに「月」を外せば、カテゴリー・商品状態で区別され、全ての欄が埋まった表ができるのではないでしょうか?

では、「月」を行から外して「カテゴリー」と「商品状態」だけで見てみましょう。

最初に作った表の行のディメンションを「カテゴリー・商品状態」だけにした表

先頭行のNULL・空欄はあるままです。

月を見ずにカテゴリーと商品状態だけで集計することで、NULLという分類や空欄はなくなる想定でした。しかし、そうならなかったのはなぜでしょうか?

理由としてリレーションシップでは、データソース画面で一致するフィールドを設定すると「どの項目どうしで結びつけるか」が決まるからです。シートに移動して使うデータを選んでも、結びつけるための手がかりがないデータは、そのまま「結び付かないデータ(=NULL)」として残るイメージです。

そのためシートで作った表から「月」を取り除いても、2つのテーブルを結びつけるための一致するフィールドには「月・カテゴリー・商品状態」が設定されたままのため、結びつかないと判定されたデータはNULLという分類や空欄となったままになります。

【ログデータ×ログデータ(欠損値あり)の場合のまとめ】

ログデータ×ログデータ(欠損値あり)でリレーションシップした場合、一致するフィールドを基準にログデータの一括りとなるデータ同士が結びつけられます。

多対多で対応しており、集計値も想定通りの値となりました。

同じデータで結合した場合:現実には発生していないデータを作り出していました(行がかけ算式に複製され、値が水増しされる)。

欠損していた部分については、欠損部分と対応するはずだったテーブルの値がNULLに分類されます。リレーションシップの一致するフィールドは、データソースを作成した時点で決定されており、設定した一致するフィールドが全て条件通りになるデータ以外は、結びつけられないためです。

データブレンドを活用すると、NULLに分類されるデータが出てくる問題を回避できるケースがあります。詳しくは次回の記事で紹介します。

補足

現実には、マスタデータ・ログデータが想定しているような構造ではなく、きれいに整っていないこともあります。

例えば、「1行が顧客と対応しているマスタデータ」と認識していたものの、実際には「顧客の契約状況を表す履歴データ」だったという想定外のケースも存在します。

このような場合、過去の契約履歴を保持していたために顧客IDが重複しており、意図していないデータが結びつくことになる場合もあります。

元のデータの1行がどのような単位なのか、欠損はあるか、などを確認し、それを意識して処理することは非常に重要です。


まとめ

この記事を通して「リレーションシップとはどんな操作なのか」についての理解が深まっていれば嬉しいです。

今回行ったリレーションシップの実践例4つについて、簡単にまとめます。

①マスタデータ×マスタデータの場合: 一致するフィールドを基準に1対1でデータを結びつけることができ、想定している通りの集計ができた。(※1対1なのは、「顧客ID=顧客1人につき1行」といったように、一致するフィールドがどちらの表の中でも重複していない場合に限る。一致するフィールドに重複があると、1対多や多対多の関係になる。)

②ログデータ×マスタデータの場合: 一致するフィールドを基準に1対多でデータを結びつけることができ、想定している通りの集計ができた。

③ログデータ×ログデータの場合: 一致するフィールドを基準に多対多でデータを結びつけることができ、想定している通りの集計ができた。シート内で使用したデータに応じてビューが作られる。計算式を作る時には、データをまたいだ計算になるかを考慮した上で、計算式を作る必要がある。

④ログデータ×ログデータ(欠損値あり)の場合: 一致するフィールドを基準に多対多でデータを結びつけることができ、想定している通りの集計ができた。データソース作成時の一致するフィールドの設定によって、結びつかないと判定されたデータはNULLという分類や空欄となったままだった。

分析の際は、データの中身を確認してから、適切にリレーションシップする必要があります。そのうえで、実際に自分の手でリレーションシップをすることで、理解がさらに深まります。

皆さんの「リレーションシップ」機能に対する理解の助けになれば幸いです

【次回予告】

次回の記事では、シート単位でデータソースの組み合わせ方などを変更する必要がある場合や、パブリッシュされたデータ ソースを結合する場合に特に便利な「データブレンド」という機能について紹介する予定です。

Tableauの公式ドキュメントでは、ほとんどのケースで結合よりもリレーションシップ機能が推奨されていますが、リレーションシップ④で示したように、全ての場合で想定どおりに結びつくわけではありません。

データブレンドについてと併せて「データ結合」についての総まとめもする予定なので、次回の記事も読んでいただけたら嬉しいです!

私が結合について勉強した時に、Satoshi Ganekoさんのnoteを参考にさせていただきました。サイトのリンクを貼らせていただきます。

Tableau の 結合、リレーションシップ(リレーション)、データブレンド(ブレンディング)を理解する

この記事をシェアする

minoRi

データをわかりやすく伝えるお手伝いをしています📈
Tableau Certified Data Analyst(2025年4月取得)

ホームツール

Tableauにおけるリレーションシップ...