10
7

More than 3 years have passed since last update.

行コンテキストとフィルターコンテキストについて 2(コンテキストのネスト)(PowerBI/PowerPivot/DAX)

Posted at

PowerBI/PowerPivot(以下、総称してDAXと呼びます)における「行コンテキスト」と「フィルターコンテキスト」という2つのコンテキストについて書きました。
今回は、コンテキストのネストについて書いてみたいと思います。また、行コンテキストを計算列以外の方法で作成し(つまり、DAX関数で作成し)、繰り返し処理を行う方法について見ていきます。

行コンテキストを作成する

前回の記事で見てきたように、計算列を作ることで、行コンテキストを作成することができます。今回はDAX関数で行コンテキストを作成してみます。
例えば、SUMXなどの末尾がXになっている関数群は、処理の過程で行コンテキストを作成し反復処理を行います。また、FILTER関数も同じく行コンテキストを作成して反復評価します(紛らわしいですがフィルター「コンテキスト」とは違います。FILTER「関数」の話です。)

例えば、次のような式を考えてみます。メジャーとして定義します。

[売上額] = SUMX(
'売上明細',
[販売数量] * [販売単価]
)

SUMXの最初の引数は、テーブルかテーブルを返す式を取ります。上記の例ではテーブルがそのまま引数に設定されているため、フィルターコンテキストで評価されたテーブルを引数として渡しています。
2番目の引数は、最初の引数として渡された対象を、行単位で繰り返し処理する内容を指定します。ここでは、販売数量列と販売単価列を掛け合わせる処理を行っています。そして、SUMX関数はこの処理結果を足し合わせる処理を行います。

処理の順序としては、以下のようになります。

1:最初の引数として与えられた対象を行単位で評価します(新たに行コンテキストを作成します)
2:行コンテキストにおいて、2番目の引数で与えられた処理内容を実行します
3:2で処理した内容を集計します

ここで着目して欲しい点は、コンテキストのネストが行われているというところです。上記の項番1で作成される行コンテキストは、最初の引数で与えられるコンテキスト(フィルターコンテキストで評価されたテーブルなど)に対して、新たな行コンテキストを追加しています。

ネストを操る

前の例で、仮に、最初の引数で与えられるコンテキストが行コンテキストであった場合、新しく追加した行コンテキストに差し替えられます。
次のようなテーブルがあったとします。(「商品」テーブルです)
20190926コンテキストのネスト1.PNG

このテーブルに対して、「定価」のランキングを新たな計算列として作成する場合を考えてみます。DAX式は次のようなものが考えられます。

[定価ランキング] =
VAR
CurrentPrice = [定価]
Return
COUNTROWS(
FILTER(
'商品',
[定価] > CurrentPrice
)
) + 1

順に見ていきましょう。
まず、FILTER関数は引数で受け取ったテーブルに対して、行コンテキストを作成します。しかし、この式は計算列として定義されています。したがって、元の行コンテキストの上に、新たに同じテーブルの行コンテキストを作成していることになります。この場合、FILTER関数の中では元の行コンテキストは無視され、新たな行コンテキストが評価されます。
ここで問題になるのが、FILTER関数の中にあるCurrentPriceです。これは、元の行コンテキストにおける[定価]を参照していなければなりません。そのため、上記の例では変数を定義し、それを使用することで元の行コンテキストの[定価]を参照することでこの問題を解決しています。
これにより、現在の[定価]よりも高い価格の商品をカウントし(COUNTROWS)、最後に+1しています(+1しないと0始まりのランキングになってしまうためです)

このように、コンテキストがネストされている場合には「現在どのコンテキストで評価されているか」を意識し、場合によってはネストを抜け出して処理させる必要があります。

上記の例では変数で解決していますが、もう少しスマートに解決する方法もあります。

[定価ランキング] =
COUNTROWS(
FILTER(
'商品',
[定価] > EARLIER([定価])
)
) + 1

EARLIER関数は、現在評価対象になっているコンテキストの「前の」コンテキストを呼び出します。ここでは、FILTER関数の呼び出し元のコンテキストである、計算列の行コンテキストを参照することになります。最初の例では同じ処理を変数を使って行っていましたが、EARLIER関数は「コンテキストのネストを1段階前に戻る」という指定ができます。(2番目の引数に数値を与えることで、2段階、3段階、、、とネストを上に辿ることもできます)

今回は主に行コンテキストのネストについて見てみましたが、フィルターコンテキストをネストしたり、フィルターコンテキストを無視したい場合はどうなるのでしょうか。次回はこのあたりについて書いてみたいと思います。

10
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
7