第2回:CALCULATE
今回使用するサンプルデータは、以下のサイトからダウンロードしてください。
1.CALCULATEの基本構文
1.1. CALCULATEとは何か
CALCULATEは、Filter Contextを変更して式を評価する関数である。
基本構文:
CALCULATE( <式>, <フィルタ条件1>, <フィルタ条件2>, ... ) 1.2. 最もシンプルな例
DEFINE MEASURE Sales[Sales Amount] = SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ) MEASURE Sales[Red Sales] = CALCULATE ( [Sales Amount], Product[Color] = "Red" ) EVALUATE SUMMARIZECOLUMNS ( Product[Brand], "Total Sales", [Sales Amount], "Red Sales", [Red Sales] ) 結果:
数値の表示を整えます。
DEFINE MEASURE Sales[Sales Amount] = SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ) MEASURE Sales[Red Sales] = CALCULATE ( [Sales Amount], Product[Color] = "Red" ) EVALUATE SUMMARIZECOLUMNS ( Product[Brand], "Total Sales", FORMAT ( [Sales Amount], "$#,##0" ), "Red Sales", FORMAT ( [Red Sales], "$#,##0" ) ) ORDER BY Sales[Sales Amount] DESC 1.3. CALCULATEの動作原理
CALCULATEは以下のステップで動作する:
- 既存のFilter Contextを取得
- 指定されたフィルタ条件を適用(追加、削除、変更)
- 新しいFilter Contextで式を評価
- 結果を返す
重要:CALCULATEは元のFilter Contextを変更せず、新しいFilter Contextを作成する。
1.4. CALCULATEによるFilter Contextの変更パターン
1.4.1. パターン1:フィルタの追加
既存のFilter Contextに、さらにフィルタを追加する。
DEFINE MEASURE Sales[Sales Amount] = SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ) MEASURE Sales[Red Sales] = CALCULATE ( [Sales Amount], Product[Color] = "Red" ) EVALUATE SUMMARIZECOLUMNS ( Product[Brand], "Total Sales", FORMAT ( [Sales Amount], "$#,##0" ), "Red Sales", FORMAT ( [Red Sales], "$#,##0" ) ) ORDER BY Sales[Sales Amount] DESC 動作:
- 既存のFilter Context(各カテゴリ)
- + Color = "Red" のフィルタ
- = 赤色の商品の売上のみ
1.4.2. パターン2:フィルタの上書き
同じ列に対するフィルタは、上書きされる。
DEFINE MEASURE Sales[Sales Amount] = SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ) MEASURE Sales[Contoso Sales] = CALCULATE ( [Sales Amount], Product[Brand] = "Contoso" ) EVALUATE SUMMARIZECOLUMNS ( Product[Brand], "Total Sales", FORMAT ( [Sales Amount], "$#,##0" ), "Contoso Sales", FORMAT ( [Contoso Sales], "$#,##0" ) ) ORDER BY [Sales Amount] DESC 動作:
- 既存のFilter Context(例:Brand)
- CALCULATEで
Brand = "Contoso"を指定 - → Brand の全てフィルターが
Brand = "Contoso"に上書きされる
外部フィルターを保持し、内部フィルターを追加するにはKEEPFILTERSを使います。
DEFINE MEASURE Sales[Sales Amount] = SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ) MEASURE Sales[Contoso Sales] = CALCULATE ( [Sales Amount], KEEPFILTERS ( Product[Brand] = "Contoso" ) ) EVALUATE SUMMARIZECOLUMNS ( Product[Brand], "Total Sales", FORMAT ( [Sales Amount], "$#,##0" ), "Contoso Sales", FORMAT ( [Contoso Sales], "$#,##0" ) ) ORDER BY Sales[Sales Amount] DESC 1.4.3. パターン3:複数列のフィルタ
DEFINE MEASURE Sales[Sales Amount] = SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ) MEASURE Sales[Red Computers Sales] = CALCULATE ( [Sales Amount], Product[Color] = "Red", Product[Category] = "Computers" ) EVALUATE SUMMARIZECOLUMNS ( Product[Brand], "Total Sales", FORMAT ( [Sales Amount], "$#,##0" ), "Red Computers Sales", FORMAT ( [Red Computers Sales], "$#,##0" ) ) ORDER BY Sales[Sales Amount] DESC 動作:
- ColorとCategoryの両方にフィルタを適用
- 複数条件はAND条件として扱われる
1.5. ALL関数ファミリー:フィルタの削除
1.5.1. ALL:すべてのフィルタを削除
ALLは、指定したテーブルまたは列のフィルタをすべて削除する。
DEFINE MEASURE Sales[Total Sales] = SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ) MEASURE Sales[All Products Sales] = CALCULATE ( [Total Sales], ALL ( Product ) ) EVALUATE SUMMARIZECOLUMNS ( Product[Category], "Total Sales", FORMAT ( [Total Sales], "$#,##0" ), "All Products Sales", FORMAT ( [All Products Sales], "$#,##0" ) ) ORDER BY Sales[Sales Amount] DESC 結果:
何が起きているか:
- "Total Sales"は各カテゴリでフィルタされる
- "All Products Sales"は、
ALL(Product)で Product テーブルのすべてのフィルタが削除される - 結果として、全製品の売上が返る
以下の様に比率を計算する際の分母でよく使われる。
1.5.2. 実務での使用例:構成比
DEFINE MEASURE Sales[Total Sales] = SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ) MEASURE Sales[Sales Share] = DIVIDE( [Total Sales], CALCULATE ( [Total Sales], ALL ( Product ) ) ) EVALUATE SUMMARIZECOLUMNS ( Product[Category], "Total Sales", FORMAT ( [Total Sales], "$#,##0" ), "Sales Share", FORMAT ( [Sales Share], "##0.0%" ) ) ORDER BY Sales[Sales Amount] DESC 計算式:
- 分子:各カテゴリの売上(Filter Contextあり)
- 分母:全カテゴリの売上(Filter Contextを削除)
- = 構成比
上位3の売り上げと売上比率
DEFINE MEASURE Sales[Total Sales] = SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ) MEASURE Sales[Sales Share] = DIVIDE( [Total Sales], CALCULATE ( [Total Sales], ALL ( Product ) ) ) VAR TopCategories = TOPN( 3, VALUES(Product[Category]), [Total Sales], DESC ) EVALUATE ADDCOLUMNS( TopCategories, "Total Sales", FORMAT ( [Total Sales], "$#,##0" ), "Sales Share", FORMAT ( [Sales Share], "##0.0%" ) ) ORDER BY Sales[Sales Amount] DESC 結果:
1.5.3 ALL vs ALLSELECTED
| 関数 | 動作 | 使用場面 |
|---|---|---|
| ALL | すべてのフィルタを削除 | 絶対値ベースの計算(全体に対する構成比) |
| ALLSELECTED | ビジュアルレベルのフィルタは保持 | 相対値ベースの計算(表示されているデータ内での構成比) |
DEFINE MEASURE Sales[Total Sales] = SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ) MEASURE Sales[Share of All] = DIVIDE ( [Total Sales], CALCULATE ( [Total Sales], ALL ( Product ) ) ) MEASURE Sales[Share of Selected] = DIVIDE ( [Total Sales], CALCULATE ( [Total Sales], ALLSELECTED ( Product ) ) ) -- SUMMARIZECOLUMNSにスライサーを直接指定 EVALUATE SUMMARIZECOLUMNS ( Product[Category], TREATAS ( -- Color のスライサーで Red を選択 { "Red" }, 'Product'[Color] ), "Sales", FORMAT ( [Total Sales], "$#,###" ), "Share of All", FORMAT ( [Share of All], "##0.00%" ), "Share of Selected", FORMAT ( [Share of Selected], "##0.00%" ) ) ORDER BY Product[Category] 違い:
- ALL:データモデル全体に対する構成比
- ALLSELECTED:ビジュアルで選択されているデータに対する構成比
1.5.4. ALLEXCEPT:特定列以外のフィルタを削除
DEFINE MEASURE Sales[Total Sales] = SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ) MEASURE Sales[Sales by Category Only] = CALCULATE ( [Total Sales], ALLEXCEPT ( Product, Product[Category] ) ) EVALUATE SUMMARIZECOLUMNS ( Product[Category], Product[Subcategory], "Sales", FORMAT ( [Total Sales], "$#,##0" ), "Sales by Category Only", FORMAT ( [Sales by Category Only], "$#,##0" ) ) ORDER BY Product[Category], Product[Subcategory] 動作:
- Product[Category] のフィルタは保持
- それ以外(Subcategory、Brand等)のフィルタは削除
- カテゴリごとの合計売上が各サブカテゴリ行に表示される
1.6. REMOVEFILTERS vs ALL
1.6.1. 2つの関数の違い
| 関数 | 動作 | 推奨 |
|---|---|---|
| REMOVEFILTERS | フィルタのみを削除 | 推奨 |
| ALL | フィルタを削除し、テーブル全体を返す | 副作用に注意 |
1.6.2. REMOVEFILTERSの使用(推奨)
DEFINE MEASURE Sales[Total Sales] = SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ) MEASURE Sales[All Products Sales] = CALCULATE ( [Total Sales], REMOVEFILTERS ( Product[Category] ) ) EVALUATE SUMMARIZECOLUMNS ( Product[Category], "Sales", [Total Sales], "All Products", [All Products Sales] ) ORDER BY Product[Category] 推奨理由:
- 意図が明確(特定のフィルタの削除のみ)
- パフォーマンスが良い
- 予期しない副作用がない
1.6.3. 複数列のフィルタ削除
DEFINE MEASURE Sales[Total Sales] = SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ) MEASURE Sales[No Product Filters] = CALCULATE ( [Total Sales], REMOVEFILTERS ( Product[Category], Product[Subcategory] ) ) -- または MEASURE Sales[No Product Filters 2] = CALCULATE ( [Total Sales], REMOVEFILTERS ( Product ) -- Productテーブル全体 ) EVALUATE SUMMARIZECOLUMNS ( Product[Category], Product[Subcategory], "Sales", [Total Sales], "No Filters", [No Product Filters] ) 1.7. FILTER関数:複雑な条件のフィルタリング
1.7.1. FILTER関数の基本
FILTERは、テーブルの各行を評価してフィルタする関数である。
基本構文:
FILTER( <テーブル>, <条件式> ) 1.7.2. 単純な条件式との違い
-- 方法1:単純な条件式(推奨:シンプルな場合) DEFINE MEASURE Sales[Computers Sales] = CALCULATE( [Total Sales], Product[Category] = "Computers" ) -- 方法2:FILTER関数(推奨:複雑な条件の場合) DEFINE MEASURE Sales[Computers Sales 2] = CALCULATE( [Total Sales], FILTER(Product, Product[Category] = "Computers") ) 両者は同じ結果だが、使い分けがある。
1.7.3. FILTERが必要な場合
OR条件
2021年3月以前は、複数列にまたがるOR条件を書く場合、明示的なFILTERが必要だったが、2021年3月から、新しい構文が導入され、複数列のOR条件も簡潔に書けるようになった。
DEFINE MEASURE Sales[Total Sales] = SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ) MEASURE Sales[Red or Contoso Sales] = CALCULATE ( [Total Sales], FILTER ( -- OR条件はFILTERを使わなければならなかった ALL ( Product[Color], Product[Brand] ), Product[Color] = "Red" || Product[Brand] = "Contoso" ) ) EVALUATE SUMMARIZECOLUMNS ( Product[Category], "Total Sales", [Total Sales], "Red or Contoso Sales", [Red or Contoso Sales] ) DEFINE MEASURE Sales[Total Sales] = SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ) MEASURE Sales[Red or Contoso Sales] = CALCULATE ( [Total Sales], Product[Color] = "Red" || Product[Brand] = "Contoso" -- CALCULATEでOR条件が書ける ) EVALUATE SUMMARIZECOLUMNS ( Product[Category], "Total Sales", [Total Sales], "Red or Contoso Sales", [Red or Contoso Sales] ) 1.7.4. FILTERのパフォーマンス注意点
-- 遅い:FILTERを使いすぎ DEFINE MEASURE Sales[Slow Measure] = CALCULATE( [Total Sales], FILTER(Sales, Sales[Amount] > 100), FILTER(Sales, Sales[Quantity] > 1), FILTER(Product, Product[Category] = "Electronics") ) -- 速い:単純な条件式を使う DEFINE MEASURE Sales[Fast Measure] = CALCULATE( [Total Sales], Sales[Amount] > 100, Sales[Quantity] > 1, Product[Category] = "Electronics" ) 原則:
- 単純な条件(1列、1値)→ 単純な条件式
- 複雑な条件(計算、複数列)→ FILTER関数











