STEP 38:DAXのフィルターコンテキスト

🎯 STEP 38: DAXのフィルターコンテキスト

DAXの心臓部!コンテキストを理解すれば無敵になれる

📋 このステップで学ぶこと

  • フィルターコンテキストとは何か(DAXの核心概念)
  • CALCULATE関数の仕組みと使い方
  • ALL・ALLSELECTED関数でフィルターを操作する方法
  • FILTER関数で複雑な条件を指定する方法
  • VALUES・DISTINCT関数で一意の値を取得する方法
  • 実践的な構成比・ランキングの計算

ゴール:フィルターコンテキストを理解し、構成比・前年比・ランキングなど高度な分析指標を作成できるようになる

🎯 1. フィルターコンテキストとは

DAXの最重要概念を理解しよう

フィルターコンテキストとは、メジャーが計算される際に「どのデータを対象にするか」を決める条件のことです。同じメジャーでも、フィルターコンテキストによって結果が変わります。これがDAXの最も重要で、最も難しい概念です。

✅ フィルターコンテキスト = メジャーの計算範囲
要素 説明
フィルター 計算対象のデータを絞り込む条件 地域 = “東京”
コンテキスト 計算が実行される「文脈」「状況」 テーブルの各行、グラフの各棒
フィルターコンテキスト 計算時点で有効なすべてのフィルターの組み合わせ 東京 × 2024年 × 商品A

同じメジャーでも結果が変わる例

具体例で理解しましょう。「売上 = SUM(売上[金額])」というシンプルなメジャーでも、使う場所によって結果が変わります。

💡 同じメジャーが異なる結果を返す例
使用場所 フィルターコンテキスト 結果
カードビジュアル(フィルターなし) なし(全データ) 10,000,000円
スライサーで「東京」を選択 地域 = “東京” 3,000,000円
商品別テーブルの「商品A」行 商品 = “商品A” 2,500,000円
マトリックスの「東京 × 商品A」セル 地域 = “東京” AND 商品 = “商品A” 800,000円

ポイント:メジャー「売上」の式は同じなのに、配置する場所によって「どのデータを集計するか」が自動的に変わります。これがフィルターコンテキストの働きです。

フィルターコンテキストを作るもの

フィルターコンテキストは、様々な要素によって作られます。これらが組み合わさって、メジャーの計算対象が決まります。

📊 フィルターコンテキストの発生源
発生源 説明 具体例
スライサー ユーザーが選択した値でフィルター 年度スライサーで「2024年」を選択
ビジュアルフィルター ビジュアルに設定されたフィルター 「売上 > 100万」のフィルター
ページフィルター ページ全体に適用されるフィルター 関東地方のみ表示
レポートフィルター レポート全体に適用されるフィルター 過去1年間のデータのみ
行・列の設定 テーブルやマトリックスの行・列 商品別テーブルの各行
グラフの軸・凡例 グラフの各要素 棒グラフの各棒、円グラフの各扇形
DAX関数(CALCULATE) DAX式内で明示的に指定するフィルター CALCULATE(…, 地域 = “東京”)
📊 フィルターコンテキストの組み合わせ例

以下のようなレポートを想像してください:

要素 設定 フィルター効果
スライサー 2024年を選択 年 = 2024
マトリックスの行 商品カテゴリ 各行でカテゴリが変わる
マトリックスの列 地域 各列で地域が変わる
売上メジャー 上記すべてのフィルターが適用

結果:各セルの売上は「2024年 AND 特定カテゴリ AND 特定地域」のフィルターがかかった状態で計算されます。

⚡ 2. CALCULATE関数 – フィルターを操作する最強関数

CALCULATEとは

CALCULATE関数は、フィルターコンテキストを「操作」できる唯一の関数です。既存のフィルターを変更・追加・削除して、メジャーを計算します。DAXで最も重要で、最も強力な関数です。

✅ CALCULATE関数の基本
項目 内容
構文 CALCULATE(式, フィルター1, フィルター2, …)
第1引数 計算したい式(メジャーや集計関数)
第2引数以降 適用したいフィルター条件(省略可、複数指定可)
複数フィルター AND条件で結合される
できること フィルターの追加、変更、削除
💻 CALCULATE関数の基本例

例1:特定の地域でフィルター

東京の売上 = 
CALCULATE(
    SUM(売上[金額]),
    売上[地域] = "東京"
)

例2:複数条件でフィルター(AND)

東京2024年売上 = 
CALCULATE(
    SUM(売上[金額]),
    売上[地域] = "東京",
    YEAR(売上[日付]) = 2024
)

例3:OR条件でフィルター

東京または大阪の売上 = 
CALCULATE(
    SUM(売上[金額]),
    売上[地域] = "東京" || 売上[地域] = "大阪"
)

※モバイルでは横スクロールで全体を確認できます

CALCULATEの重要な動作:フィルターの上書き

CALCULATEの重要な特徴として、既存のフィルターを上書きするという動作があります。これを理解することが非常に重要です。

💡 フィルターの上書きルール
状況 動作 結果
スライサーで「大阪」を選択 地域 = “大阪” のフィルターが有効 大阪の売上が表示
メジャーでCALCULATE(…, 地域 = “東京”) スライサーの「大阪」を「東京」で上書き 東京の売上が表示

ポイント:CALCULATEで指定したフィルターは、同じ列の既存フィルターを上書きします。これにより「スライサーで何を選んでも東京の売上を表示」といった固定値のメジャーが作れます。

📊 フィルター上書きの活用例
用途 メジャー例
比較基準を固定 東京基準 = CALCULATE(SUM(売上[金額]), 売上[地域] = “東京”)
特定期間の固定 2023年売上 = CALCULATE(SUM(売上[金額]), YEAR(売上[日付]) = 2023)
全体との比較 全体売上 = CALCULATE(SUM(売上[金額]), ALL(売上))

🔄 3. ALL関数 – フィルターを完全削除する

ALL関数の基本

ALL関数は、指定したテーブルまたは列のすべてのフィルターを無視します。「全体の合計」や「構成比の分母」を計算するときに必須の関数です。

✅ ALL関数の基本
項目 内容
構文 ALL(テーブル名) または ALL(テーブル名[列名])
機能 指定したテーブル/列のすべてのフィルターを無視する
使い方 CALCULATEの第2引数以降で使用
主な用途 全体売上、構成比の分母、ランキング計算
💻 ALL関数の使用例

例1:すべてのフィルターを無視(全体売上)

全体売上 = 
CALCULATE(
    SUM(売上[金額]),
    ALL(売上)
)

例2:特定の列のフィルターのみ無視

全地域売上 = 
CALCULATE(
    SUM(売上[金額]),
    ALL(売上[地域])
)

違い:ALL(売上)はすべてのフィルターを無視。ALL(売上[地域])は地域フィルターのみ無視(年や商品のフィルターは有効のまま)。

ALL関数の最重要用途:構成比の計算

ALL関数の最も重要な用途は構成比(シェア)の計算です。分子は現在のフィルターで計算し、分母はALLでフィルターを無視して全体を計算します。

💡 構成比の計算パターン

メジャーの定義:

売上構成比(%) = 
DIVIDE(
    SUM(売上[金額]),
    CALCULATE(
        SUM(売上[金額]),
        ALL(商品)
    )
) * 100

計算の流れ:

要素 計算内容 例(商品Aの行)
分子 SUM(売上[金額]) 商品Aの売上 = 2,500,000
分母 CALCULATE(…, ALL(商品)) 全商品の売上 = 10,000,000
結果 分子 ÷ 分母 × 100 2,500,000 ÷ 10,000,000 × 100 = 25%
✅ 構成比の表示結果例
商品 売上 構成比
商品A 2,500,000円 25.0%
商品B 3,500,000円 35.0%
商品C 4,000,000円 40.0%
合計 10,000,000円 100.0%

ALLEXCEPT – 特定の列以外のフィルターを無視

ALLEXCEPT関数は、「指定した列以外の」すべてのフィルターを無視します。特定の軸でのシェア計算に便利です。

📊 ALLEXCEPT関数
項目 内容
構文 ALLEXCEPT(テーブル, 保持する列1, 保持する列2, …)
機能 指定した列のフィルターは保持し、それ以外をすべて無視
使用例 商品別の地域シェア、カテゴリ内での商品シェア
💻 ALLEXCEPT使用例
// 商品フィルターは保持し、他(地域、年など)は無視
商品内シェア = 
DIVIDE(
    SUM(売上[金額]),
    CALCULATE(
        SUM(売上[金額]),
        ALLEXCEPT(売上, 売上[商品])
    )
) * 100

効果:「商品A全体のうち、東京が何%か」のような計算ができます。商品のフィルターは保持されるため、商品Aの行では商品Aの全売上が分母になります。

🎨 4. ALLSELECTED関数 – ビジュアルの選択範囲を尊重する

ALLとALLSELECTEDの違い

ALLSELECTED関数は、スライサーやページフィルターは保持しつつ、ビジュアル内のフィルター(行・列)だけを無視します。「ユーザーの選択を尊重した構成比」を計算するときに使います。

💡 ALLとALLSELECTEDの比較
フィルター種類 ALL ALLSELECTED
スライサー ❌ 無視 ✅ 保持
ページフィルター ❌ 無視 ✅ 保持
レポートフィルター ❌ 無視 ✅ 保持
ビジュアル内(行・列) ❌ 無視 ❌ 無視
💻 ALLSELECTED使用例
// スライサーの選択範囲内での構成比
選択範囲内構成比(%) = 
DIVIDE(
    SUM(売上[金額]),
    CALCULATE(
        SUM(売上[金額]),
        ALLSELECTED(商品)
    )
) * 100
📊 ALLSELECTEDの動作例

シナリオ:スライサーで「東京」を選択したとき

商品 売上 ALL使用の構成比 ALLSELECTED使用の構成比
商品A 800,000円 8.0%(全国比) 26.7%(東京内)
商品B 1,000,000円 10.0%(全国比) 33.3%(東京内)
商品C 1,200,000円 12.0%(全国比) 40.0%(東京内)
合計 3,000,000円 30.0% 100.0%

ポイント:ALLSELECTEDを使うと、ユーザーが選択した範囲(東京)内での構成比が計算されます。合計が100%になるのが特徴です。

🔍 5. FILTER関数 – 複雑な条件でフィルタリング

FILTER関数の基本

FILTER関数は、テーブルの各行を評価して、条件を満たす行のみを返す関数です。単純な「列 = 値」では表現できない複雑な条件を指定するときに使います。

✅ FILTER関数の基本
項目 内容
構文 FILTER(テーブル, 条件式)
第1引数 フィルタリング対象のテーブル
第2引数 各行に対して評価する条件式
戻り値 条件を満たす行のみを含むテーブル
使用場面 複数列の計算、動的条件、メジャー参照が必要な場合
💻 FILTER関数の使用例

例1:単価が10,000円以上の商品の売上

高額商品売上 = 
CALCULATE(
    SUM(売上[金額]),
    FILTER(
        商品,
        商品[単価] >= 10000
    )
)

例2:複数条件(AND)

高額かつ在庫あり = 
CALCULATE(
    SUM(売上[金額]),
    FILTER(
        商品,
        商品[単価] >= 10000 && 商品[在庫] > 0
    )
)

CALCULATEとFILTERの使い分け

単純な条件ならCALCULATEの直接指定、複雑な条件ならFILTERを使います。

💡 CALCULATEとFILTERの使い分け
条件の種類 推奨
単純な等値比較 CALCULATE 売上[地域] = “東京”
単純な範囲比較 CALCULATE 売上[金額] > 10000
複数列の計算が必要 FILTER 単価 × 数量 > 100000
メジャーを参照する条件 FILTER 売上が平均以上の商品
動的な条件 FILTER 前年比がプラスの商品
💻 FILTERの高度な使用例:平均以上の売上商品
平均以上商品の売上 = 
VAR 平均売上 = AVERAGE(売上[金額])
RETURN
    CALCULATE(
        SUM(売上[金額]),
        FILTER(
            ALL(商品),
            CALCULATE(SUM(売上[金額])) >= 平均売上
        )
    )

解説:VAR(変数)で平均売上を計算し、FILTERで各商品の売上が平均以上かを判定しています。

📊 6. VALUES・DISTINCT関数 – 一意の値を取得する

VALUES関数の基本

VALUES関数は、現在のフィルターコンテキストで見える一意の値のリストを返します。「いくつの商品が選択されているか」「どの地域が選択されているか」を調べるときに使います。

✅ VALUES関数の基本
項目 内容
構文 VALUES(テーブル名[列名])
機能 現在のフィルターで見える一意の値のテーブルを返す
よく使う組み合わせ COUNTROWS(VALUES(…)) で一意の値の数を取得
DISTINCTとの違い VALUESはBLANK行を含む、DISTINCTはBLANKを1つにまとめる
💻 VALUES関数の使用例

例1:選択された商品の数

選択商品数 = COUNTROWS(VALUES(商品[商品名]))

例2:単一選択時のみ値を表示

選択状態 = 
IF(
    COUNTROWS(VALUES(売上[地域])) = 1,
    "選択中: " & SELECTEDVALUE(売上[地域]),
    "複数地域選択中"
)
💡 SELECTEDVALUE関数
項目 内容
構文 SELECTEDVALUE(列, [代替値])
機能 フィルターで1つの値のみ選択されている場合、その値を返す
複数選択時 代替値を返す(省略時はBLANK)
使用例 タイトルの動的表示、条件分岐

🎯 7. 実践的なフィルター操作

実務で使えるメジャー集

ここまで学んだ関数を組み合わせて、実務で使えるメジャーを作成してみましょう。

💻 実践メジャー①:全社比率
// 1. 全社売上(すべてのフィルターを無視)
全社売上 = 
CALCULATE(
    SUM(売上[金額]),
    ALL(売上)
)

// 2. 全社比率
全社比率(%) = 
DIVIDE(
    SUM(売上[金額]),
    [全社売上]
) * 100
💻 実践メジャー②:選択範囲内構成比
// スライサー選択を尊重した構成比
選択内構成比(%) = 
DIVIDE(
    SUM(売上[金額]),
    CALCULATE(
        SUM(売上[金額]),
        ALLSELECTED(商品)
    )
) * 100
💻 実践メジャー③:ランキングとTop N判定
// 売上ランキング
売上ランク = 
RANKX(
    ALL(商品[商品名]),
    SUM(売上[金額]),
    ,
    DESC,
    DENSE
)

// Top5判定
Top5判定 = 
IF(
    [売上ランク] <= 5,
    "⭐ Top5",
    ""
)

// Top5の売上合計
Top5売上合計 = 
CALCULATE(
    SUM(売上[金額]),
    TOPN(
        5,
        ALL(商品[商品名]),
        CALCULATE(SUM(売上[金額])),
        DESC
    )
)
💻 実践メジャー④:条件付き色分け用スコア
// 売上ランク(A/B/C/D)
売上評価 = 
VAR 現在売上 = SUM(売上[金額])
VAR 平均売上 = CALCULATE(AVERAGE(売上[金額]), ALL(商品))
VAR 上位25% = CALCULATE(
    PERCENTILEX.INC(ALL(商品), SUM(売上[金額]), 0.75)
)
RETURN
    SWITCH(
        TRUE(),
        現在売上 >= 上位25%, "A",
        現在売上 >= 平均売上, "B",
        現在売上 >= 平均売上 * 0.5, "C",
        "D"
    )
✅ 実践メジャーの活用結果例
商品 売上 全社比率 ランク Top5 評価
商品C 4,000,000円 40.0% 1 ⭐ Top5 A
商品B 3,500,000円 35.0% 2 ⭐ Top5 A
商品A 2,500,000円 25.0% 3 ⭐ Top5 B

📝 STEP 38 のまとめ

✅ このステップで学んだこと
  • フィルターコンテキスト:メジャーが計算される条件(範囲)
  • CALCULATE:フィルターを操作する最強関数
  • ALL:すべてのフィルターを無視(全体値の計算に使用)
  • ALLSELECTED:スライサーは保持、ビジュアル内フィルターは無視
  • ALLEXCEPT:指定列以外のフィルターを無視
  • FILTER:複雑な条件でフィルタリング
  • VALUES:現在のコンテキストで見える一意の値を取得
💡 最重要ポイント

DAXの本質は「フィルターコンテキストの操作」です!

CALCULATEとALL系関数を使いこなせば、「構成比」「前年比」「ランキング」など、あらゆる分析が可能になります。

最初は難しく感じても、「今、どのフィルターが効いているか」を常に意識すれば、必ず理解できます。

フィルターコンテキストはDAXの心臓部です!

📝 実践演習

演習 1 基礎

以下のメジャーを作成してください:
1. 東京の売上(CALCULATEでフィルター)
2. 全体売上(ALLですべてのフィルターを無視)
3. 東京の売上が全体に占める割合(%)

【基本的なCALCULATEとALL】
// 1. 東京の売上
東京の売上 = 
CALCULATE(
    SUM(売上[金額]),
    売上[地域] = "東京"
)

// 2. 全体売上(すべてのフィルターを無視)
全体売上 = 
CALCULATE(
    SUM(売上[金額]),
    ALL(売上)
)

// 3. 東京の売上が全体に占める割合(%)
東京シェア(%) = 
DIVIDE(
    [東京の売上],
    [全体売上]
) * 100

動作確認:

  • スライサーで「大阪」を選択しても、東京の売上が表示される
  • 全体売上は常に同じ値(すべてのフィルター無視)
  • 東京シェアは約30%前後(データによる)
演習 2 応用

商品別の売上構成比を計算するメジャーを作成してください。ただし、スライサーで地域を選択した場合は、その地域内での構成比が表示されるようにしてください。

【ALLSELECTEDを使った構成比】
// 商品売上
商品売上 = SUM(売上[金額])

// 構成比(スライサー対応)
商品構成比(%) = 
DIVIDE(
    [商品売上],
    CALCULATE(
        [商品売上],
        ALLSELECTED(商品)
    )
) * 100

動作例:

シナリオ 商品A構成比 合計
フィルターなし 25.0%(全国内) 100%
「東京」選択時 26.7%(東京内) 100%

ポイント:

  • ALLSELECTED(商品)で商品の行フィルターのみ無視
  • 地域のスライサーフィルターは保持される
  • 結果:選択された地域内での商品構成比が計算される
演習 3 発展

以下の高度なメジャーを作成してください:
1. Top5商品の売上合計
2. Top5商品が全体に占める割合(%)
3. 現在の商品がTop5に入っているか判定するメジャー

【TOPNとRANKXを使った高度な分析】
// 1. Top5商品の売上合計
Top5売上合計 = 
CALCULATE(
    SUM(売上[金額]),
    TOPN(
        5,
        ALL(商品[商品名]),
        CALCULATE(SUM(売上[金額])),
        DESC
    )
)

// 2. Top5商品が全体に占める割合(%)
Top5シェア(%) = 
DIVIDE(
    [Top5売上合計],
    CALCULATE(SUM(売上[金額]), ALL(売上))
) * 100

// 3. Top5に入っているか判定
Top5判定 = 
VAR 現在ランク = 
    RANKX(
        ALL(商品[商品名]),
        CALCULATE(SUM(売上[金額])),
        ,
        DESC,
        DENSE
    )
RETURN
    IF(現在ランク <= 5, "⭐ Top5", "")

解説:

関数 役割
TOPN 売上上位N件の商品を取得
RANKX 現在の商品が何位かを計算
ALL(商品) すべての商品を対象にランキング
VAR 計算結果を変数に格納して再利用

❓ よくある質問

Q1: CALCULATEとFILTERの使い分けがわかりません
シンプルな条件ならCALCULATE、複雑ならFILTERです。

CALCULATE推奨:
  • 列 = 値 の単純比較
  • 読みやすさ重視
  • パフォーマンス重視
例:CALCULATE(SUM(売上[金額]), 売上[地域] = "東京")

FILTER推奨:
  • 複数列の計算が必要
  • 他のメジャーを参照する条件
  • 動的な条件
例:FILTER(商品, 商品[単価] * 商品[在庫] > 100000)
Q2: ALLとALLSELECTEDの違いがよくわかりません
スライサーを保持するかどうかです。

ALL:すべてのフィルターを完全無視
使用例:全社売上、全期間売上など

ALLSELECTED:スライサーやページフィルターは保持
使用例:選択範囲内での構成比、ランキングなど

迷ったら:「ユーザーの選択を尊重したいか?」
→ YES:ALLSELECTED
→ NO:ALL
Q3: 構成比が100%を超えてしまいます
分母のALL系関数の指定範囲を確認してください。

間違い例:
DIVIDE(SUM(売上[金額]), CALCULATE(SUM(売上[金額]), ALL(売上[地域])))
→ 地域のフィルターのみ無視なので、商品別だと100%超える

正しい例:
DIVIDE(SUM(売上[金額]), CALCULATE(SUM(売上[金額]), ALL(商品)))
→ 商品のフィルターを無視して全商品の合計を分母に

「何に対する構成比か」を明確にして、その軸のフィルターをALLで無視します。
Q4: CALCULATEの中でCALCULATEを使えますか?
はい、ネストできます。

ただし、読みにくくなるので、できれば変数(VAR)を使いましょう:
前年東京売上 = 
VAR 東京売上 = 
    CALCULATE(SUM(売上[金額]), 売上[地域] = "東京")
RETURN
    CALCULATE(
        東京売上, 
        SAMEPERIODLASTYEAR(日付[Date])
    )
Q5: フィルターコンテキストがわからなくなったときは?
以下の方法でデバッグしましょう。

1. カードビジュアルで確認
メジャーをカードに配置して、フィルターなしの値を確認

2. テーブルで分解
商品別、地域別などに分割して、どこで値がおかしいか特定

3. 中間メジャーを作成
複雑な式を分解して、各ステップの値を確認

4. VALUESで確認
COUNTROWS(VALUES(列))で、いくつの値がフィルターされているか確認
📝

学習メモ

BIツール入門 - Step 38

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE