🎯 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(式, フィルター1, フィルター2, …) |
| 第1引数 | 計算したい式(メジャーや集計関数) |
| 第2引数以降 | 適用したいフィルター条件(省略可、複数指定可) |
| 複数フィルター | AND条件で結合される |
| できること | フィルターの追加、変更、削除 |
例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(テーブル名[列名]) |
| 機能 | 指定したテーブル/列のすべてのフィルターを無視する |
| 使い方 | CALCULATEの第2引数以降で使用 |
| 主な用途 | 全体売上、構成比の分母、ランキング計算 |
例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(テーブル, 保持する列1, 保持する列2, …) |
| 機能 | 指定した列のフィルターは保持し、それ以外をすべて無視 |
| 使用例 | 商品別の地域シェア、カテゴリ内での商品シェア |
// 商品フィルターは保持し、他(地域、年など)は無視
商品内シェア =
DIVIDE(
SUM(売上[金額]),
CALCULATE(
SUM(売上[金額]),
ALLEXCEPT(売上, 売上[商品])
)
) * 100
効果:「商品A全体のうち、東京が何%か」のような計算ができます。商品のフィルターは保持されるため、商品Aの行では商品Aの全売上が分母になります。
🎨 4. ALLSELECTED関数 – ビジュアルの選択範囲を尊重する
ALLとALLSELECTEDの違い
ALLSELECTED関数は、スライサーやページフィルターは保持しつつ、ビジュアル内のフィルター(行・列)だけを無視します。「ユーザーの選択を尊重した構成比」を計算するときに使います。
| フィルター種類 | ALL | ALLSELECTED |
|---|---|---|
| スライサー | ❌ 無視 | ✅ 保持 |
| ページフィルター | ❌ 無視 | ✅ 保持 |
| レポートフィルター | ❌ 無視 | ✅ 保持 |
| ビジュアル内(行・列) | ❌ 無視 | ❌ 無視 |
// スライサーの選択範囲内での構成比
選択範囲内構成比(%) =
DIVIDE(
SUM(売上[金額]),
CALCULATE(
SUM(売上[金額]),
ALLSELECTED(商品)
)
) * 100
シナリオ:スライサーで「東京」を選択したとき
| 商品 | 売上 | 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(テーブル, 条件式) |
| 第1引数 | フィルタリング対象のテーブル |
| 第2引数 | 各行に対して評価する条件式 |
| 戻り値 | 条件を満たす行のみを含むテーブル |
| 使用場面 | 複数列の計算、動的条件、メジャー参照が必要な場合 |
例1:単価が10,000円以上の商品の売上
高額商品売上 =
CALCULATE(
SUM(売上[金額]),
FILTER(
商品,
商品[単価] >= 10000
)
)
例2:複数条件(AND)
高額かつ在庫あり =
CALCULATE(
SUM(売上[金額]),
FILTER(
商品,
商品[単価] >= 10000 && 商品[在庫] > 0
)
)
CALCULATEとFILTERの使い分け
単純な条件ならCALCULATEの直接指定、複雑な条件ならFILTERを使います。
| 条件の種類 | 推奨 | 例 |
|---|---|---|
| 単純な等値比較 | CALCULATE | 売上[地域] = “東京” |
| 単純な範囲比較 | CALCULATE | 売上[金額] > 10000 |
| 複数列の計算が必要 | FILTER | 単価 × 数量 > 100000 |
| メジャーを参照する条件 | FILTER | 売上が平均以上の商品 |
| 動的な条件 | FILTER | 前年比がプラスの商品 |
平均以上商品の売上 =
VAR 平均売上 = AVERAGE(売上[金額])
RETURN
CALCULATE(
SUM(売上[金額]),
FILTER(
ALL(商品),
CALCULATE(SUM(売上[金額])) >= 平均売上
)
)
解説:VAR(変数)で平均売上を計算し、FILTERで各商品の売上が平均以上かを判定しています。
📊 6. VALUES・DISTINCT関数 – 一意の値を取得する
VALUES関数の基本
VALUES関数は、現在のフィルターコンテキストで見える一意の値のリストを返します。「いくつの商品が選択されているか」「どの地域が選択されているか」を調べるときに使います。
| 項目 | 内容 |
|---|---|
| 構文 | VALUES(テーブル名[列名]) |
| 機能 | 現在のフィルターで見える一意の値のテーブルを返す |
| よく使う組み合わせ | COUNTROWS(VALUES(…)) で一意の値の数を取得 |
| DISTINCTとの違い | VALUESはBLANK行を含む、DISTINCTはBLANKを1つにまとめる |
例1:選択された商品の数
選択商品数 = COUNTROWS(VALUES(商品[商品名]))
例2:単一選択時のみ値を表示
選択状態 =
IF(
COUNTROWS(VALUES(売上[地域])) = 1,
"選択中: " & SELECTEDVALUE(売上[地域]),
"複数地域選択中"
)
| 項目 | 内容 |
|---|---|
| 構文 | SELECTEDVALUE(列, [代替値]) |
| 機能 | フィルターで1つの値のみ選択されている場合、その値を返す |
| 複数選択時 | 代替値を返す(省略時はBLANK) |
| 使用例 | タイトルの動的表示、条件分岐 |
🎯 7. 実践的なフィルター操作
実務で使えるメジャー集
ここまで学んだ関数を組み合わせて、実務で使えるメジャーを作成してみましょう。
// 1. 全社売上(すべてのフィルターを無視)
全社売上 =
CALCULATE(
SUM(売上[金額]),
ALL(売上)
)
// 2. 全社比率
全社比率(%) =
DIVIDE(
SUM(売上[金額]),
[全社売上]
) * 100
// スライサー選択を尊重した構成比
選択内構成比(%) =
DIVIDE(
SUM(売上[金額]),
CALCULATE(
SUM(売上[金額]),
ALLSELECTED(商品)
)
) * 100
// 売上ランキング
売上ランク =
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. 東京の売上(CALCULATEでフィルター)
2. 全体売上(ALLですべてのフィルターを無視)
3. 東京の売上が全体に占める割合(%)
// 1. 東京の売上
東京の売上 =
CALCULATE(
SUM(売上[金額]),
売上[地域] = "東京"
)
// 2. 全体売上(すべてのフィルターを無視)
全体売上 =
CALCULATE(
SUM(売上[金額]),
ALL(売上)
)
// 3. 東京の売上が全体に占める割合(%)
東京シェア(%) =
DIVIDE(
[東京の売上],
[全体売上]
) * 100
動作確認:
- スライサーで「大阪」を選択しても、東京の売上が表示される
- 全体売上は常に同じ値(すべてのフィルター無視)
- 東京シェアは約30%前後(データによる)
商品別の売上構成比を計算するメジャーを作成してください。ただし、スライサーで地域を選択した場合は、その地域内での構成比が表示されるようにしてください。
// 商品売上
商品売上 = SUM(売上[金額])
// 構成比(スライサー対応)
商品構成比(%) =
DIVIDE(
[商品売上],
CALCULATE(
[商品売上],
ALLSELECTED(商品)
)
) * 100
動作例:
| シナリオ | 商品A構成比 | 合計 |
|---|---|---|
| フィルターなし | 25.0%(全国内) | 100% |
| 「東京」選択時 | 26.7%(東京内) | 100% |
ポイント:
- ALLSELECTED(商品)で商品の行フィルターのみ無視
- 地域のスライサーフィルターは保持される
- 結果:選択された地域内での商品構成比が計算される
以下の高度なメジャーを作成してください:
1. Top5商品の売上合計
2. Top5商品が全体に占める割合(%)
3. 現在の商品がTop5に入っているか判定するメジャー
// 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 | 計算結果を変数に格納して再利用 |
❓ よくある質問
CALCULATE推奨:
- 列 = 値 の単純比較
- 読みやすさ重視
- パフォーマンス重視
FILTER推奨:
- 複数列の計算が必要
- 他のメジャーを参照する条件
- 動的な条件
ALL:すべてのフィルターを完全無視
使用例:全社売上、全期間売上など
ALLSELECTED:スライサーやページフィルターは保持
使用例:選択範囲内での構成比、ランキングなど
迷ったら:「ユーザーの選択を尊重したいか?」
→ YES:ALLSELECTED
→ NO:ALL
間違い例:
DIVIDE(SUM(売上[金額]), CALCULATE(SUM(売上[金額]), ALL(売上[地域])))
→ 地域のフィルターのみ無視なので、商品別だと100%超える
正しい例:
DIVIDE(SUM(売上[金額]), CALCULATE(SUM(売上[金額]), ALL(商品)))
→ 商品のフィルターを無視して全商品の合計を分母に
「何に対する構成比か」を明確にして、その軸のフィルターをALLで無視します。
ただし、読みにくくなるので、できれば変数(VAR)を使いましょう:
前年東京売上 =
VAR 東京売上 =
CALCULATE(SUM(売上[金額]), 売上[地域] = "東京")
RETURN
CALCULATE(
東京売上,
SAMEPERIODLASTYEAR(日付[Date])
)
1. カードビジュアルで確認
メジャーをカードに配置して、フィルターなしの値を確認
2. テーブルで分解
商品別、地域別などに分割して、どこで値がおかしいか特定
3. 中間メジャーを作成
複雑な式を分解して、各ステップの値を確認
4. VALUESで確認
COUNTROWS(VALUES(列))で、いくつの値がフィルターされているか確認
学習メモ
BIツール入門 - Step 38