見出し画像

Power BI - ALL、ALLEXCEPT、ALLSELECTED関数の違い

'ALL'の付くDAX関数は、
たまに使おうとすると (ALL関数はよく使うかもしれませんが) 
どういう関数だったか迷うことがあると思います。(僕だけ?)

MSのリファレンス上は「フィルター関数」に該当し、
次の5つが現時点で存在します。

1. ALL
2. ALLSELECTED
3. ALLEXCEPT
4. ALLCROSSFILTERED
5. ALLNOBLANKROW


このうち、ALLALLEXCEPTALLSELECTEDの3つは
「3兄弟」みたいな関数なので、まとめて覚えておくとよいです。

ALLCROSSFILTERED関数については、最近新たに追加された関数なので、また時間があれば書こうと思います。

3つの関数の共通点と違い

これらの3つの関数の共通点は、
メジャーで計算対象とするテーブルにかかっている
フィルターを除去するためのDAX関数ということです。

どうして3つもフィルター除去に係る関数があるのかというと、
フィルターの除去対象を調整するためです。

まとめ(メジャーを使った例)

具体例を用いてまとめてみました。
「列1」~「列5」を持つ「Fact」テーブルがあり、
「列4」と「列5」にはフィルターがかかっている、という前提です。

画像7

① 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)だけ残して、それ以外の列を削除しました。

画像2

Dateを制御するために、カレンダーテーブルも作成し、
リレーションシップは以下のように設定しました。

画像3

そして、メジャーを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])
    )


これらのメジャーを使って、
次のようなレポートを作成しました。


画像5

※マトリックスの「Sales」列には、暗黙のメジャーを適用していますので、
明示的に式を書くと、「Sales = SUM(financials[ Sales])」と同じです。

まず注目するべきは、ALL_Salesです。

画像6

financialsテーブルに係る全てのフィルターがALL関数によって除去されているので、左のYearフィルターで年度を「2014」に絞り込んでいることを無視して、前年度分の合計を計算しています。

ここまでは、「当然そうなるよね」と予想の範疇なのですが、

次に、左のMonthフィルターで、「12」月を外してみると、
ちょっと意外な結果になります。

画像7

まず、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]を集計対象とするようにメジャーを書いたはずなのに、
思いっきり左のスライサーでフィルターされた影響を受けています!

画像7

このように、ALLSELECTED関数は、外部のフィルターの影響を受けるということを念頭に置いて、ALLEXCEPT関数との違いを認識しておかないと、
思わぬ計算ミスを招くので、留意が必要です。

(ちなみに、上記レポートの場合は、ALLEXCEPT関数では意図したレポートが作成できないので、「外部のフィルターの影響を受ける」ALLSELECTED関数を意図的に使う必要があります。
ALLSLECTED関数は、ALL関数やALLEXCEPT関数よりも後から追加(PowerPivot v2以降)追加された関数であることからして、外部のフィルターを残しつつ、内部のフィルターを除去するニーズに応じて設計された関数なのかもしれない、と僕はひそかに思っています)


以上になります。

いいなと思ったら応援しよう!