PowerBI/PowerPivot(以下、総称してDAXと呼びます)における重要な要素として、計算列とメジャーについての記事を書きました。この記事内では、計算列は行レベルで値を参照し、メジャーはテーブルの集計として主に機能する、と書いています。
厳密に言えば、これらは、「行コンテキスト」と「フィルターコンテキスト」という2つの異なるコンテキストで評価されている、ということになります。DAXを理解するうえで重要な2つのコンテキストについて、少し書いてみたいと思います。
評価コンテキストについて
DAX式は常にコンテキストに沿って評価されます。式が評価される環境、と考えることができます。
例えば、次のような式を考えてみます。
[売上額] = SUMX('売上明細',[販売数量] * [販売単価])
これは、売上テーブルの数量の全ての値に商品価格を掛けた合計です。この式をメジャーで使用すると、売上の総計になります。
このメジャーを適用したままテーブルにフィルターを掛けると、この売上合計(売上額フィールド)の値は総合計ではなく、フィルターに影響を受けた数値になります。このことは直感的に理解できると思います。
すなわち、上記の式は、「現在のフィルターによって表示される売上の合計」として解釈することができます。
今度は、次のような式を考えてみます。計算列として下記のDAX式を定義します。
[粗利]= [定価] - [原価]
この式も直感的に理解できると思います。定価列の値から原価列の値を減算して粗利を計算するものです。
しかし、振り返って考えてみると、どの行の値を参照するべきかを指示していません。参照する行は暗黙的に決定されています。すなわち、計算列のなかでは、テーブルを行単位で反復評価し、現在の行を自動的に参照しているということが分かります。
ここまではとても当たり前の話であり、わざわざ分けて考えることでもないと感じるかもしれません。ですが、より深くDAX式を駆使するためには、フィルターコンテキストと行コンテキスト、これら2つのコンテキストのうちどちらで式が評価されるかという意識を持つことが非常に重要です。
計算列での集計
次のような式を計算列として定義します。
[売上合計(計算列)] = SUM('売上明細',[販売数量] * [販売単価])
計算列であるため、行別に評価されます。テーブルの各行において、販売数量と販売単価を掛けて売上合計を算出しようとしています。が、結果として、この式はうまく機能しません。各行に表示されるのは「売上額の総合計」になってしまいます。なぜでしょうか。
SUM関数はフィルターコンテキストで評価されます。行単位で評価されません。これを計算列で使用するとDAXは行コンテキストを無視して、フィルターコンテキストで評価します。そのため、表示される値は売上高の総合計になってしまいます。
これを意図通りに計算したければ、次の式を定義すれば解決します。
計算列を次のように作成します。
[売上] = [販売数量] * [販売単価]
そして、メジャーで次のような式を定義します。
[売上額] = SUM([売上])
こうすると各行で意図通りの売上額が表示されます。
しかし、よく考えると、この式では各行の評価はなされていないはずです。それなのに、表示される結果はちゃんと商品カテゴリ別に細分化された合計額になっています。
この点についても、フィルターコンテキストで評価されているという点を振り返れば理解しやすくなります。つまり、「合計」の値からスタートして、それがフィルターによって細分化された合計値が各行に表示されていると理解することができます。
メジャーでの列参照
今度は、次の式をメジャーとして定義します。
[粗利] = [定価] - [原価]
これは計算列では意図通りに計算できました。メジャーではどうでしょうか。結果は、メジャーではこの式はエラーになってしまいます。
メジャーの中では、基本的にはフィルターコンテキストで評価されます。そのため、暗黙的に「現在の行」を取得することができないのです。この式をメジャーで正しく動作させるには、次のように書き直す必要があります。
[粗利] = SUM([定価]) - SUM([原価])
この書き方でも、各行の値は正確に表示されます。SUMによって合計されていますが、結果的にはフィルターによって各行の値(各行単位のフィルターによって絞り込まれた項目の合計値)になっています。
フィルターコンテキストと行コンテキストについて、少し細かく見てみました。直感的に理解できていることをあえて難しく書いているように思われるかもしれません。
「繰り返し処理」や「コンテキストのネスト」を使った処理を行う際には、これらのコンテキストについての理解が必要になってきます。式のなかでどのようなコンテキストが使われているかをある程度意識しながら計算式を組み立てることができれば、さらにDAXを使いこなすことができます。