Power BI - ALL、ALLEXCEPT、ALLSELECTED関数の違い
'ALL'の付くDAX関数は、
たまに使おうとすると (ALL関数はよく使うかもしれませんが)
どういう関数だったか迷うことがあると思います。(僕だけ?)
MSのリファレンス上は「フィルター関数」に該当し、
次の5つが現時点で存在します。
1. ALL
2. ALLSELECTED
3. ALLEXCEPT
4. ALLCROSSFILTERED
5. ALLNOBLANKROW
このうち、ALLとALLEXCEPTとALLSELECTEDの3つは
「3兄弟」みたいな関数なので、まとめて覚えておくとよいです。
ALLCROSSFILTERED関数については、最近新たに追加された関数なので、また時間があれば書こうと思います。
3つの関数の共通点と違い
これらの3つの関数の共通点は、
メジャーで計算対象とするテーブルにかかっている
フィルターを除去するためのDAX関数ということです。
どうして3つもフィルター除去に係る関数があるのかというと、
フィルターの除去対象を調整するためです。
まとめ(メジャーを使った例)
具体例を用いてまとめてみました。
「列1」~「列5」を持つ「Fact」テーブルがあり、
「列4」と「列5」にはフィルターがかかっている、という前提です。
① ALL( 'Fact' )
ALL関数は、引数として指定したテーブル('Fact') にかかる全てのフィルターを除去します。
具体例では、
「列4」と「列5」にそれぞれかかっているフィルターを取り除いて、
何もフィルタリングされていない元々のFactテーブルを結果として返します。
② ALLEXCEPT('Fact' , 'Fact'[列4])
ALLEXCEPT関数は、指定した列に係るフィルター"以外の"全てのフィルターを除去します。(選択的にフィルターを除去する)
具体例では、
「列4」を引数として指定したため、
「列4」のフィルターだけを残して、
その他のフィルター(「列5」にかかっているフィルター)を除去したFactテーブルを結果として返します。
③ ALLSELECTED('Fact' , 'Fact'[列4])
ALLSELECTED関数は、指定した列に係るフィルター"だけ”を除去します。(選択的にフィルターを残す)
具体例では、
「列4」を引数として指定したため、
「列4」のフィルターだけを除去して、
その他のフィルターを残したFactテーブルを結果として返します。
ALLEXCEPTとALLSELECTEDの使い分け
上記説明の通り、ALLEXCEPT関数とALLSELECTED関数は、
指定した列(引数)に対して、逆の結果を返します。
多数の列を持つテーブルに、
一部の列に係るフィルターだけ残したり、除去したい場合は、
フィルターを残す列を指定する方が楽なのか(→ALLEXCEPTを使用)、
フィルターを除去する列を指定する方が楽なのか(→ALLSELECTEDを使用)
というのも1つの使い分けの判断軸ですが、
実は、使い方によっては、必ずしも真逆の結果になりません。
次の具体例を見てみてください。
具体例2 -ALLEXCEPTとALLSELECTEDの相違点(外部からのフィルターの影響も除去するのか、しないのか)
いつものように、MSのサンプルデータを使わせてもらいます。
説明のために使用する列(DateとSales)だけ残して、それ以外の列を削除しました。
Dateを制御するために、カレンダーテーブルも作成し、
リレーションシップは以下のように設定しました。
そして、メジャーを3つ作成しました。
ALLを使ったメジャー
ALL_Sales =
CALCULATE(
SUM(financials[ Sales]),
ALL(dim_calendar)
)
※ちなみに、ALL関数はテーブルを指定することもできますが、列を単独もしくは複数、指定することもできます。DAX式を書く時のお作法として、ALLでテーブル全体を指定することは推奨されておらず、面倒でも欲しい結果を出すためにフィルターを外しておきたい最小限の列を、個別に指定(例: ALL ( [列1] , [列2]) )しておく癖をつけた方がよいです。
ALLEXCEPTを使ったメジャー
ALLEXCEPT_Sales =
CALCULATE(
SUM(financials[ Sales]),
ALLEXCEPT(dim_calendar,dim_calendar[Year])
)
ALLSELECTEDを使ったメジャー
ALLSELECTED_Sales =
CALCULATE(
SUM(financials[ Sales]),
ALLSELECTED(dim_calendar[Month])
)
これらのメジャーを使って、
次のようなレポートを作成しました。
※マトリックスの「Sales」列には、暗黙のメジャーを適用していますので、
明示的に式を書くと、「Sales = SUM(financials[ Sales])」と同じです。
まず注目するべきは、ALL_Salesです。
financialsテーブルに係る全てのフィルターがALL関数によって除去されているので、左のYearフィルターで年度を「2014」に絞り込んでいることを無視して、前年度分の合計を計算しています。
ここまでは、「当然そうなるよね」と予想の範疇なのですが、
次に、左のMonthフィルターで、「12」月を外してみると、
ちょっと意外な結果になります。
まず、Monthの「12」の選択を外したため、
右のマトリックス表の最左列「Month」からも「12」がなくなりました。
それと同時に、「Sales」列の合計もMonth「1」からMonth「11」までの合計に調整されました。
また、ALLEXCEPT関数で作成したメジャー(ALLEXCEPT_Sales)も、「Year」以外のフィルターを除去して、(つまり全ての「Month」を対象として)値を集計してくれています。(マトリックス表が1~11までのMonthしか表示していないのに、ALLEXCEPT_Salesは1~12までのMonthの合計を表示していることは、レポートとしてはアウトなのですが、DAX式を書く際は、Monthのフィルターを外すことを意図していたので、それでOKなのです)
しかし!!
ALLSELECTED関数で作成したメジャーは、
全ての[Month]を集計対象とするようにメジャーを書いたはずなのに、
思いっきり左のスライサーでフィルターされた影響を受けています!
このように、ALLSELECTED関数は、外部のフィルターの影響を受けるということを念頭に置いて、ALLEXCEPT関数との違いを認識しておかないと、
思わぬ計算ミスを招くので、留意が必要です。
(ちなみに、上記レポートの場合は、ALLEXCEPT関数では意図したレポートが作成できないので、「外部のフィルターの影響を受ける」ALLSELECTED関数を意図的に使う必要があります。
ALLSLECTED関数は、ALL関数やALLEXCEPT関数よりも後から追加(PowerPivot v2以降)追加された関数であることからして、外部のフィルターを残しつつ、内部のフィルターを除去するニーズに応じて設計された関数なのかもしれない、と僕はひそかに思っています)
以上になります。