第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関数











