Salesforce 結合レポートをマスターする:コンサルタントが解説するクロスオブジェクト分析の秘訣

背景と適用シナリオ

Salesforce コンサルタントとして、私たちがお客様から頻繁に受ける要望の一つに、「複数の異なるビジネスプロセスやオブジェクトにまたがるデータを、単一のビューで可視化したい」というものがあります。例えば、営業担当役員は「現在進行中の商談と、同じ取引先に関連する進行中のカスタマーサポートのケース(Cases)を一覧で確認し、ビジネスの全体像を把握したい」と考えるかもしれません。また、マーケティングマネージャーは「特定のキャンペーン(Campaigns)から創出されたリード(Leads)と、そのリードが最終的に成立させた商談(Opportunities)を並べて分析し、キャンペーンの真の ROI を測定したい」と考えるでしょう。

Salesforce の標準レポート機能は非常に強力ですが、通常は単一のレポートタイプ(Report Type)に基づいています。これは、主従関係や参照関係で直接リンクされたオブジェクトのデータを分析するには十分ですが、直接的なリレーションシップを持たないオブジェクト間のデータを並べて比較することは困難です。例えば、「取引先」オブジェクトを介して間接的につながっている「商談」と「ケース」を、それぞれ独立した情報ブロックとして一つのレポートで表示することは、標準のサマリーレポートやマトリックスレポートでは実現できません。

ここで登場するのが Joined Reports (結合レポート) です。Joined Reports は、この課題を解決するために設計された、Salesforce の標準機能の中でも特に強力な分析ツールです。この機能を利用することで、最大5つまでの異なるレポートブロックを一つのインターフェースに統合し、共通の項目でデータをグルーピングして表示することができます。これにより、コーディングや外部の BI ツールを必要とせずに、複雑なビジネス上の問いに答えるための包括的なインサイトを得ることが可能になります。

具体的な適用シナリオ:

  • 取引先の360度ビュー: ある取引先に関連する「進行中の商談」「未完了の活動(Activities)」「オープン中のケース」を並べて表示し、営業担当者が顧客との次のアクションを計画する際の全体像を提供します。
  • 営業パイプラインとサポートの連携分析: 価値の高い商談を抱える取引先で、同時に深刻なサポートケースが発生していないかを確認し、顧客満足度の低下による失注リスクを事前に特定します。
  • キャンペーン効果測定: 特定のキャンペーンに関連する「リード」「進行中の商談」「成立した商談」をブロックごとに表示し、リード獲得から受注までのコンバージョンファネル全体を一枚のレポートで可視化します。
  • ユーザの活動分析: 各ユーザが所有する「オープン中の商談」「完了した ToDo」「対応中のケース」を比較し、チームメンバーの生産性や業務負荷を多角的に評価します。

このように、Joined Reports は、サイロ化しがちな部門間のデータを繋ぎ、ビジネスの状況をより深く、多角的に理解するための鍵となる機能です。


原理の説明

Joined Reports の中核的なコンセプトは、複数の独立したレポートを「ブロック」として扱い、それらを共通の軸で束ねることにあります。この仕組みを理解することが、効果的なレポートを作成する第一歩です。

ブロック (Blocks)

Joined Reports は、最大5つのブロック (Blocks) で構成されます。各ブロックは、それ自体が独立したレポートと考えることができます。つまり、それぞれのブロックは以下の要素を個別に持ちます。

  • レポートタイプ (Report Type): 各ブロックは、異なるレポートタイプを持つことができます。「商談」レポートタイプ、「ケース」レポートタイプ、「キャンペーンとリード」レポートタイプなどを自由に組み合わせることが可能です。
  • 列 (Columns): ブロックごとに表示したい項目(列)を自由に選択できます。
  • 検索条件 (Filters): ブロックごとに固有の検索条件を適用できます。例えば、ブロック1では「完了予定日が今期」の商談を表示し、ブロック2では「状況が進行中」のケースのみを表示する、といった設定が可能です。
  • 並び替え (Sorting): 各ブロック内のデータの並び替え順を個別に設定できます。

レポートビルダー上では、これらのブロックが横に並んで表示され、直感的にレポートを構築していくことができます。

共通の項目によるグルーピング (Grouping by Common Fields)

Joined Reports の最も重要な特徴は、各ブロックを共通の項目 (Common Fields) でグルーピングする点にあります。この共通項目が、異なるデータセットを結びつける「糊」の役割を果たします。

例えば、「商談」レポートと「ケース」レポートを結合する場合を考えます。この二つのオブジェクトは、どちらも「取引先名 (Account Name)」という共通の項目を持っています。この「取引先名」をグルーピング項目として設定すると、レポートは取引先ごとに行がまとめられ、その取引先に属する商談データ(ブロック1)とケースデータ(ブロック2)が横並びで表示されます。

重要なのは、グルーピングに使用する項目は、各ブロックのレポートタイプに含まれている必要があるということです。Salesforce は、レポートにブロックを追加する際に、互換性のある(共通の項目を持つ)レポートタイプを自動的に提示してくれます。

このグルーピングの仕組みは、SQL の JOIN とは少し異なります。これは、いわゆる Outer Join(外部結合)のように動作します。つまり、ある取引先に商談しか存在せずケースが存在しない場合でも、その取引先はレポートに表示され、ケースのブロック部分は空白になります。逆もまた同様です。これにより、どちらか一方にしかデータが存在しない場合でも、全体像から漏れることがありません。


示例代码

Joined Reports の作成と編集は、Salesforce のレポートビルダー上で行う宣言的なプロセスであり、通常 Apex や Visualforce で直接コードを書くことはありません。しかし、作成した Joined Reports のデータを外部システム連携やカスタムコンポーネントで利用するために、Analytics REST API を通じてプログラムで実行し、その結果を取得することは非常に一般的です。ここでは、Analytics REST API を使用して Joined Reports を実行し、その独特な JSON レスポンスを解析する方法を解説します。

以下の例は、指定したレポートIDのレポートを非同期で実行し、その結果を取得するリクエストとレスポンスのサンプルです。

APIリクエスト例:レポートの実行

まず、レポートIDを指定して、レポートの実行をリクエストします。ここでは、`POST` メソッドで `/services/data/v58.0/analytics/reports/{reportId}/instances` エンドポイントを呼び出します。

// HTTP Request
POST /services/data/v58.0/analytics/reports/00Oxx00000A0001EAA/instances

// Request Body (JSON)
// This example runs the report without any overriding filters.
// You could add filters in the reportMetadata if needed.
{
  "reportMetadata": {
  }
}

このリクエストが成功すると、Salesforce はレポートインスタンスIDを含むレスポンスを返します。次に、このインスタンスIDを使って結果を取得します。

APIレスポンス例:結合レポートの結果

インスタンスIDを使って `/services/data/v58.0/analytics/reports/{reportId}/instances/{instanceId}` に `GET` リクエストを送ることで、レポート結果を取得できます。Joined Reports のレスポンスは、その構造が特徴的です。

// HTTP Response Body (JSON)
{
  "reportMetadata": {
    "reportFormat": "JOINED",
    // ... other metadata
  },
  "factMap": {
    // T!Tキーは、レポート全体の総計 (Grand Total) を表します
    "T!T": {
      "aggregates": [
        { "label": "Sum of Amount", "value": 1500000 },
        { "label": "Record Count", "value": 15 }
      ],
      "rows": []
    },
    // 0!Tキーは、ブロック0 (最初のブロック) の総計を表します
    "0!T": {
      "aggregates": [
        { "label": "Sum of Amount", "value": 1200000 },
        { "label": "Record Count", "value": 10 }
      ],
      "rows": []
    },
    // 1!Tキーは、ブロック1 (2番目のブロック) の総計を表します
    "1!T": {
      "aggregates": [
        { "label": "Record Count", "value": 5 }
      ],
      "rows": []
    },
    // 'キー' はグルーピングされた行のデータを示します。
    // この例では、'Edge Communications' という取引先名でグルーピングされています。
    // キーの最初の数字はグルーピングレベルを示します。
    "0_0!T": {
      // '0_0' は最初のグルーピングの最初の値 (Edge Communications) のサマリーです。
      // T は合計 (Total) を意味します。
      "aggregates": [
        { "label": "Sum of Amount", "value": 500000 },
        { "label": "Record Count", "value": 7 }
      ]
    },
    // '0_0!0' は、グルーピング 'Edge Communications' 内のブロック0のデータ行を示します。
    "0_0!0": {
      "rows": [
        {
          "dataCells": [
            { "label": "Edge Communications", "value": "Edge Communications" },
            { "label": "Opportunity A", "value": "Opportunity A" },
            { "label": "250000", "value": 250000 }
          ]
        },
        {
          "dataCells": [
            { "label": "Edge Communications", "value": "Edge Communications" },
            { "label": "Opportunity B", "value": "Opportunity B" },
            { "label": "250000", "value": 250000 }
          ]
        }
      ]
    },
    // '0_0!1' は、グルーピング 'Edge Communications' 内のブロック1のデータ行を示します。
    "0_0!1": {
      "rows": [
        {
          "dataCells": [
            { "label": "Edge Communications", "value": "Edge Communications" },
            { "label": "High Priority Case 001", "value": "High Priority Case 001" },
            { "label": "New", "value": "New" }
          ]
        }
      ]
    }
  },
  "groupingsDown": {
    "groupings": [
      {
        "key": "0",
        "label": "Edge Communications",
        "value": "Edge Communications"
      },
      {
        "key": "1",
        "label": "Burlington Textiles Corp of America",
        "value": "Burlington Textiles Corp of America"
      }
    ]
  }
}

この JSON 構造のキーは `factMap` です。このマップのキーは `(groupingKey)!(blockKey)` という形式をしています。`T` は総計を意味し、数字はグループやブロックのインデックスを示します。この構造を正しくパースすることで、各ブロックのデータをグルーピングごとに正確に取得し、カスタムUIや外部システムで活用することができます。


注意事項

Joined Reports は非常に強力なツールですが、コンサルタントとしてお客様に提案・導入する際には、いくつかの制約と注意点を理解しておく必要があります。

権限 (Permissions)

  • レポートの実行と作成: ユーザーが Joined Reports を実行・作成・編集するには、プロファイルまたは権限セットで「レポートの実行」および「レポートビルダーでレポートを作成およびカスタマイズ」権限が必要です。
  • フォルダアクセス権: レポートはフォルダに保存されるため、対象のレポートフォルダへの「参照」以上のアクセス権が必要です。
  • オブジェクトと項目レベルのセキュリティ: レポートに表示されるデータは、実行ユーザーのオブジェクト権限および項目レベルセキュリティ(FLS)に従います。ユーザーがアクセスできないオブジェクトや項目はレポートに表示されません。

機能的な制限 (Functional Limitations)

  • ブロックの数: 1つの Joined Report に含めることができるブロックは最大5つです。
  • ダッシュボードコンポーネント: Joined Report からグラフを作成し、そのグラフをダッシュボードに追加することは可能です。ただし、レポート全体をテーブル形式でダッシュボードに表示することはできません。
  • レポート登録 (Subscription): Lightning Experience では Joined Reports の登録(定期的なメール配信)が可能ですが、Salesforce Classic ではサポートされていません。
  • -
  • クロス条件 (Cross Filters): Joined Reports ではクロス条件(例:「商談がある取引先」など)を使用することはできません。クロス条件が必要な場合は、各ブロックのレポートタイプを事前にカスタマイズするか、別のレポートで対応する必要があります。
  • バケット項目 (Bucket Fields): バケット項目は各ブロック内で作成・使用できますが、ブロックをまたいで共通のグルーピング項目として使用することはできません。
  • エクスポート: Joined Reports は「書式設定されたレポート」としてのみエクスポート可能です。「詳細のみ」のエクスポートオプションは利用できないため、CSVでの詳細なデータ加工を目的とする場合は不向きです。
  • グラフの種類: Joined Reports のグラフでは、積み上げ横棒グラフやドーナツグラフなど、一部利用できないグラフ種別があります。

パフォーマンスと API 制限

  • パフォーマンス: 非常に多くのデータを持つオブジェクトを複数のブロックで結合する場合、レポートの実行に時間がかかることがあります。特に複雑な条件や多くのグルーピングレベルを持つレポートはパフォーマンスに影響を与える可能性があるため、不要なデータは検索条件で極力絞り込むことが推奨されます。
  • API 制限: Analytics REST API を介して Joined Reports を頻繁に実行する場合、組織の標準的な API コール制限にカウントされます。バッチ処理などで大量に呼び出す際は、ガバナ制限を考慮した設計が必要です。

まとめとベストプラクティス

Joined Reports は、Salesforce 内に散在するデータを統合し、ビジネスの全体像を一枚の絵として描き出すための強力な宣言的ツールです。コンサルタントとして、この機能をマスターすることは、お客様の複雑なレポーティング要件に対して、迅速かつコードレスなソリューションを提供する上で不可欠です。

ベストプラクティス

  1. 明確なビジネス上の問いから始める: レポート作成に着手する前に、「このレポートで何を明らかにしたいのか?」というビジネス上の問いを具体的に定義します。例えば、「主要取引先におけるアップセルの機会(商談)と、その取引先が抱える問題(ケース)の相関関係は?」といった具体的な問いが、効果的なレポート設計の出発点となります。
  2. 適切なレポートタイプの選択: 各ブロックで必要となる項目が含まれ、かつ、共通のグルーピング項目を持つレポートタイプを慎重に選択します。標準のレポートタイプで要件を満たせない場合は、カスタムレポートタイプの作成を検討します。
  3. シンプルさを維持する: 最大5つのブロックが利用可能ですが、必ずしもすべてを使い切る必要はありません。まずは2つのブロックから始め、レポートが意図通りに機能することを確認してから、必要に応じてブロックを追加していくアプローチが効果的です。レポートが複雑になりすぎると、かえってインサイトが読み取りにくくなります。
  4. 視覚化を活用する: レポートにグラフを追加することで、データの傾向や重要なポイントを直感的に伝えることができます。特に、異なるブロックの主要な指標(例:商談の金額とケースの件数)を比較するようなグラフは、経営層への報告などで非常に有効です。
  5. ユーザー教育の実施: Joined Reports のフォーマットは、一般的なレポートと異なるため、エンドユーザーがその読み方を理解できるよう、トレーニングを実施することが重要です。「なぜこのブロックは空白なのか」「この総計は何を意味するのか」といった点を明確に説明し、ユーザーがレポートから正しいインサイトを得られるように支援します。
  6. 限界を認識する: Joined Reports は万能ではありません。リアルタイムのデータ集計や、非常に大規模なデータセットの分析、複雑なデータ変換が必要な場合は、CRM Analytics (旧 Tableau CRM) や、外部のデータウェアハウスとの連携といった、より高度なソリューションの適用を検討すべきです。コンサルタントとしては、ツールの限界を理解し、最適なソリューションを提案する能力が求められます。

これらのベストプラクティスを念頭に置くことで、Joined Reports の真価を最大限に引き出し、お客様のデータ駆動型の意思決定を力強く支援することができるでしょう。

コメント