DAX の数式のコンテキスト
コンテキストを使用すると動的分析を行うことができます。動的分析では、現在の行またはセルの選択や関連データを反映するために数式の結果が変わることがあります。高性能な動的分析の作成や、数式に関する問題のトラブルシューティングを行うには、コンテキストをよく理解して効果的に使用することが重要です。
ここでは、行コンテキスト、クエリ コンテキスト、フィルター コンテキストという 3 種類のコンテキストの定義と、計算列やピボットテーブルの数式のコンテキストが評価される方法について説明します。
このセクションの最後に、数式の結果がコンテキストによってどのように変化するのかを示す詳細な例へのリンクが記載されています。
コンテキストの概要
PowerPivot の数式は、ピボットテーブルに適用されたフィルター、テーブル間のリレーションシップ、および数式で使用されるフィルターの影響を受けます。コンテキストとは、動的分析の実行を可能にするものです。 数式の作成とトラブルシューティングを行うには、コンテキストについての理解が重要となります。
コンテキストには、行コンテキスト、クエリ コンテキスト、フィルター コンテキストという種類があります。
行コンテキストは "現在の行" と考えることができます。計算列を作成した場合、個々の行に格納されている値と、現在の行に関連した列の値で、行コンテキストが構成されます。また、一部の関数は、テーブル全体で演算を実行する際に現在の行から値を取得してその値を使用します (EARLIER および EARLIEST)。
クエリ コンテキストとは、行の見出しと列の見出しに応じてピボットテーブルの各セルに暗黙的に作成されるデータのサブセットです。
フィルター コンテキストは、行に適用されているフィルター制約または数式内のフィルター式で定義されているフィルター制約に基づく、各列の許容値のセットです。
それぞれの種類のコンテキストの詳細については、「DAX の数式のコンテキスト」を参照してください。
トップに戻る
行コンテキスト
計算列に数式を作成した場合、その数式の行コンテキストは、現在の行内の全列からの値を含んでいます。テーブルが別のテーブルに関連付けられている場合、コンテキストには、現在の行に関連付けられている他のテーブルの値もすべて含まれます。
たとえば、同じテーブルの 2 つの列を加算する =[Freight] + [Tax] という計算列を作成したとします。この数式は、同じ行の各値を自動的に参照する Excel テーブルの数式と同じように動作します。テーブルは範囲とは異なることに注意してください。範囲表記を使用して、現在の行の前にある行から値を参照したり、テーブルまたはセル内の任意の単一の値を参照したりすることはできません。常にテーブルと列を使用する必要があります。
行コンテキストで、関連するテーブル内のどの行を現在の行に関連付けるかは、自動的にテーブル間のリレーションシップに従って決定されます。
たとえば次の数式は、RELATED 関数を使用し、注文の出荷先の地域に基づいて、関連テーブルから税の値をフェッチします。現在のテーブル内の地域の値を使用し、関連するテーブルで地域を探し、関連するテーブルから該当する地域の税率を取得することによって、税の値が求められます。
= [Freight] + RELATED('Region'[TaxRate])
この数式は、Region テーブルから現在の地域の税率を取得するだけです。テーブル間を接続するキーを知る必要や指定する必要はありません。
複数行のコンテキスト
DAX には、テーブルで計算を繰り返し実行する関数が含まれています。これらの関数は、現在の行と、現在の行のコンテキストを、複数持つことができます。プログラミングの観点では、内側および外側ループを再帰的に処理する数式を作成できます。
たとえば、Products と Sales という 2 つのテーブルがブックに含まれている場合に、複数の製品に関連する取引が多数存在する sales テーブル全体から、各製品の 1 回の取引あたりの最大注文数を検索するとします。
Excel では、この計算には一連の中間出力が必要であり、データが変更されると中間出力の再構築が必要となります。Excel のパワー ユーザーであれば、ジョブを行う配列数式を作成することもできます。または、リレーショナル データベースでは、入れ子にしたサブセレクトを記述できます。
ただし、DAX を使用すると、正しい値を返す 1 つの数式を作成でき、データをテーブルに追加すると結果が自動的に更新されます。
=MAXX(FILTER(Sales,[ProdKey]=EARLIER([ProdKey])),Sales[OrderQty])
この数式の詳細なチュートリアルについては、「EARLIER 関数 (DAX)」を参照してください。
つまり、EARLIER 関数は、現在の操作に先行する操作からの行コンテキストを格納します。この関数は常に、メモリに 2 つのコンテキスト セットを格納します。1 つのコンテキスト セットは、数式の内側のループに対する現在行を表し、もう一方のセットは、数式の外側のループに対する現在行を表します。DAX では、2 つのループの間で値が自動的に提供されるので、複雑な集計を作成することができます。
クエリ コンテキスト
クエリ コンテキストとは、数式に対して暗黙的に取得されるデータのサブセットを指します。ピボットテーブルのセルにメジャーまたは他の値のフィールドをドロップすると、PowerPivot エンジンが、行見出しと列見出し、スライサー、およびレポート フィルターを調べてコンテキストを決定します。その後、PowerPivot エンジンが必要な計算を行って、ピボットテーブルの各セルに値を生成します。取得されるデータのセットは、各セルのクエリ コンテキストです。
数式を配置した場所によってコンテキストが変わるので、数式の結果も、多数のグループおよびフィルターを持つピボットテーブルで数式を使用したか、またはコンテキストが最少かつフィルターのない計算列で数式を使用したかによって変わります。
たとえば、Sales テーブルの Profit 列の値を合計する =SUM('Sales'[Profit]) という単純な数式を作成したとします。この数式を Sales テーブル内の計算列で使用した場合、数式の結果はテーブル全体について同じになります。なぜなら、この数式のクエリ コンテキストは常に Sales テーブルのデータセット全体であるためです。計算結果には、すべての地域、すべての製品、すべての年度の利益が含まれます。
ただし、同じ結果を何百回も表示する必要はなく、特定の年度、特定の国、特定の製品、または、そうした条件の組み合わせについて、該当する利益を計算し、総計を求めるのが普通です。
ピボットテーブルでは、列見出しや行見出し、スライサーを追加したり削除したりすることで、簡単にコンテキストを変更できます。上記のようなメジャーの数式を作成し、ピボットテーブルにドロップできます。ピボットテーブルに列または行の見出しを追加するたびに、メジャーが評価されるクエリ コンテキストが変化します。スライス操作やフィルター処理もコンテキストに影響を及ぼします。したがって、ピボットテーブルで使用される同じ数式は、セルごとに異なるクエリ コンテキストで評価されます。
フィルター コンテキスト
フィルター コンテキストは、数式の引数を使用して列やテーブルの使用可能な値のセットにフィルター制約を指定すると追加されます。行コンテキストやクエリ コンテキストなど、他のコンテキストに加えて適用されます。
たとえば、ピボットテーブルでは、クエリ コンテキストに関する前のセクションで説明したように、行見出しと列見出しに基づいて各セルの値が計算されます。ただし、ピボットテーブルに追加されるメジャーや計算列の中では、フィルター式を指定して、数式で使用される値を制御できます。また、特定の列のフィルターを選択的にクリアすることもできます。
数式内にフィルターを作成する方法の詳細については、「FILTER 関数 (DAX)」を参照してください。
フィルターをクリアして総計を作成する方法の例については、「ALL 関数 (DAX)」を参照してください。
数式内のフィルターを選択的にクリアして適用する方法の例については、「ALLEXCEPT 関数 (DAX)」を参照してください。
このため、数式の結果を解釈するときにフィルター コンテキストがわかるように、ピボットテーブルで使用されているメジャーや数式の定義を確認する必要があります。
数式のコンテキストの決定
数式を作成する場合、PowerPivot for Excel ではまず一般的な構文を確認し、次に、指定された列およびテーブルの名前を、現在のコンテキストで使用可能な列およびテーブルと照合します。PowerPivot で、数式によって指定された列またはテーブルが見つからない場合は、エラーになります。
コンテキストは、前のセクションで説明したように、ブック内の使用可能なテーブル、テーブル間のリレーションシップ、および適用されたフィルターを使用して決定されます。
たとえば、新しいテーブルにデータをインポートしたばかりで、フィルターを適用していない場合は、テーブルの列セット全体が現在のコンテキストに含まれます。複数のテーブルがリレーションシップでリンクされていて、対象のピボットテーブルが列見出しの追加やスライサーの使用によってフィルター処理されている場合は、それらの関連テーブルと、データに対するフィルターが、コンテキストに含まれます。
コンテキストは、数式のトラブルシューティングも困難にする可能性がある強力な概念です。簡単な数式およびリレーションシップで開始してコンテキストの機能を確認してから、ピボットテーブルで簡単な数式を試すことをお勧めします。次のセクションでは、数式でさまざまなタイプのコンテキストを使用して動的に結果を返す方法の例も示します。
数式のコンテキストの例
RELATED 関数は、関連列の値が含まれるように現在の行のコンテキストを拡大します。これにより、参照を実行できます。このトピックには、フィルター処理と行コンテキストの相互作用の例が含まれています。
FILTER 関数を使用すると、現在のコンテキストに含める行を指定できます。このトピックの例では、集計を行う別の関数にフィルターを埋め込む方法も示されています。
ALL 関数は、数式内でコンテキストを設定します。この関数を使用すると、クエリ コンテキストの結果として適用されたフィルターをオーバーライドできます。
ALLEXCEPT 関数を使用すると、指定した以外のすべてのフィルターを削除できます。どちらのトピックにも、数式の作成と複雑なコンテキストの理解に役立つ例が含まれています。
EARLIER 関数と EARLIEST 関数を使用すると、内側のループの値を参照しながら計算を実行してテーブルをループ処理することができます。再帰の概念や内側と外側のループについてよく知っている場合は、このトピックを読むと EARLIER および EARLIEST 関数の威力がわかります。これらの概念についてよく知らなくても、例の手順に注意して従うことで、計算で内側と外側のコンテキストがどのように使用されるのかを理解できます。
参照整合性
ここでは、リレーションシップによって関連付けられた PowerPivot テーブル内の不足値に関連した高度な概念について説明します。このセクションは、複数のテーブルや複雑な数式を含むブックがある場合に、結果を理解するのに役立ちます。
リレーショナル データの概念について詳しくない場合は、概要を説明した「リレーションシップの概要」を先に参照することをお勧めします。
参照整合性と PowerPivot リレーションシップ
PowerPivot では、有効なリレーションシップを定義する際に 2 つのテーブル間に参照整合性を適用する必要はありません。 代わりに、それぞれの一対多のリレーションシップの "一" 側に空白行が作成され、関連付けられたテーブルのすべての一致しない行を処理するために使用されます。この行は、SQL 外部結合として効果的に動作します。
ピボットテーブルでは、リレーションシップの "一" 側でデータをグループ化する場合、リレーションシップの "多" 側の一致しないデータも同時にグループ化され、空白の行見出しを持つ合計に含められます。この空白の見出しは、"不明なメンバー" とほぼ同じ意味です。
不明なメンバーについて
不明なメンバーの概念は、SQL Server Analysis Services などの多次元データベース システムを使用した経験があるユーザーには、親しみがあるかもしれません。この用語を初めて聞く場合は、次の例を参照して、不明なメンバーがどのようなものであり、それが計算にどのように影響するのかを理解してください。
店舗ごとに月次売上を合計する計算を作成するとします。ただし、Sales テーブルの列に店舗名の値がありません。Store テーブルと Sales テーブルを店舗名で関連付けると、数式の結果はどのようになるでしょうか。ピボットテーブルでは既存の店舗に関連付けられていない売上額をどのようにグループ化し、表示すべきでしょうか。
この問題は、データ ウェアハウスでよく見られる問題です。データ ウェアハウスでは、ファクトの分類と計算に使用する、店舗、領域、および他の属性に関する情報を含むディメンション テーブルに、ファクト データの大きなテーブルを論理的に関連付ける必要があります。この問題を解決するために、既存のエンティティに関連付けられていない新しいファクトは一時的に不明なメンバーに割り当てられます。関連付けられていないファクトが、ピボットテーブルの空白見出しの元にグループ化されるのは、このためです。
空白値と空白行の処理の相違
空白値は、不明なメンバーに対応するために追加される空白行とは異なります。空白値は、NULL、空の文字列、その他の不足値などを表すために使用される特殊な値です。空白値および他の DAX データ型の詳細については、「PowerPivot ブックでサポートされるデータ型」を参照してください。