Power BIのレポートを作っていると、「行の値はそれっぽいのに、合計行だけ数字が合わない」「マトリクスの合計が、表示されている行を足した結果にならない」といった現象に必ずぶつかります。これはバグではなく、DAXがそういう考え方で計算するからです。
そのうえで、合計がズレる問題を正しく直す鍵が、SUMXに代表されるイテレーター関数です。power bi dax iterator という言葉で調べる人が多いのも、まさにここがつまずきポイントだからです。
この記事では、SUMXなどを「いつ使うべきか」「なぜ合計がズレるのか」「どう直すのが筋が良いのか」を、できるだけ噛み砕いて整理します。
1. まず結論:合計がズレる一番の理由
DAXのメジャーは、ビジュアルの各セル(各行)で一度ずつ計算されます。そして合計行も、「各行の結果を足し算」しているのではなく、合計行のフィルター条件でメジャーをもう一回計算しています。
つまりこうです。
-
行:その行の条件でメジャーを計算
-
合計:合計の条件(行より広い条件)でメジャーを再計算
この仕組みのせいで、次のような計算はズレやすくなります。
-
割合(利益率、構成比、達成率)
-
平均(平均単価、平均日次、平均処理時間)
-
何かを丸めてから合計する計算
-
条件分岐で行ごとに計算式が変わるもの
そして、行ごとの計算を意図どおり積み上げたいときに登場するのがSUMXです。
2. SUMとSUMXは何が違うのか(超重要)
SUM:列をそのまま足す
SUMは「ある列の値を、そのまま合計」します。
-
できること:Sales[Amount] を合計する
-
苦手なこと:Quantity * UnitPrice のような式を行ごとに作って合計する
SUMX:テーブルを1行ずつ回して、式を評価して足す
SUMXは「指定したテーブルを1行ずつ見て、各行で式を計算して、それを合計」します。
イメージはこうです。
-
1行目を取り出す
-
式を計算する
-
結果を足し込む
-
次の行へ…を最後まで繰り返す
例えば、売上金額が列として存在しない(単価と数量しかない)場合。
売上 =
SUMX(
Sales,
Sales[数量] * Sales[単価]
)
SUMではできない「行単位の計算→合計」ができる。これが基本の使いどころです。
3. イテレーター関数を使うべき典型パターン
パターンA:行単位の掛け算・引き算・条件分岐がある
以下はSUMX向きです。
-
数量×単価=売上
-
原価×数量=原価
-
1行ごとに割引率が違う、税率が違う
-
1行ごとに通貨レートが違う(取引日レートなど)
-
1行ごとに四捨五入してから合計したい(請求明細の端数処理)
例:明細単位で丸めてから合計する(合計後に丸めるのとは結果がズレることがあります)
請求金額 =
SUMX(
Sales,
ROUND(Sales[数量] * Sales[単価], 0)
)
パターンB:割合や平均を「表示行の足し算」で合計したい
利益率のような指標は、合計行が「全体の利益÷全体の売上」になりがちです。これは多くの場合、正しい集計です。
ただし、業務要件として「各部門の利益率を足した数」を合計として見せたい、というような要望が出ることがあります(会計的には変ですが、報告上そうしたい場面がある)。
そのときは、合計行で「表示行の粒度」を明示して回す必要があり、SUMXが役に立ちます。
パターンC:同じメジャーでも、明細と合計で粒度を切り替えたい
マトリクスでよくあるのがこれです。
-
行(明細):その行の計算ロジック
-
合計:明細の結果を足し上げるロジック
この「合計だけ別ロジック」は、DAXでは普通にやります。むしろ、やらないとビジネスで欲しい形にならないことが多いです。
4. 合計が合わない代表例と、ズレ方の正体
ここからが本題です。合計がズレる原因を、よくある形で分解します。
原因1:合計行は「足し算」ではなく「再計算」だから
例:利益率
利益 = [売上] - [原価]
利益率 =
DIVIDE([利益], [売上])
この利益率を、部門別に表示するとこうなります。
-
部門A:Aの利益率
-
部門B:Bの利益率
-
合計:全社の利益率(全社利益÷全社売上)
合計が「部門Aの利益率 + 部門Bの利益率」にならないのは当たり前です。合計は「全体条件で再計算」されているからです。
解決策:合計で“どの粒度を足すのか”を決める
もし合計を「表示されている部門ごとの利益率の足し算」に寄せたいなら、こうします。
利益率_表示行合計 =
SUMX(
VALUES(部門[部門名]),
[利益率]
)
ポイントは、SUMXで回す対象を Sales のような明細テーブルにしないことです。ここで欲しいのは「部門ごとの1行」なので、VALUES(部門[部門名]) のように、粒度を固定して回します。
原因2:SUMXで回している粒度がズレている(回し過ぎ・回さな過ぎ)
SUMXは強力ですが、「どのテーブルを回すか」で結果が変わります。
例えば、顧客別の売上を並べたビジュアルで、合計が二重計上っぽくなる場合があります。これは、
-
Sales(明細)を回すと、明細行ぶんだけ足し込む
-
顧客(ディメンション)を回すと、顧客ぶんだけ足し込む
という違いがそのまま結果に出るからです。
よくある悪い例(明細を回してしまう)
「顧客ごとの売上を足したい」のに、Salesを回すと、想定より細かい単位で計算してしまうことがあります。
解決策:回す対象は“欲しい粒度”に合わせる
顧客単位で積み上げたいなら、顧客で回します。
顧客別売上の合計として扱いたい =
SUMX(
VALUES(顧客[顧客ID]),
[売上]
)
製品単位なら製品、店舗単位なら店舗。合計が欲しい粒度に合わせて、VALUESやSUMMARIZEで“回す単位”を作るのがコツです。
原因3:丸めや最低保証など、行ごとに処理してから足したいのに、合計で一括処理している
例:1明細ごとに最低請求100円、のようなルール。
-
明細ごとに MAX(計算結果, 100) をして合計したい
-
でも合計側で MAX(全体, 100) をしてしまうと意味が変わる
解決策:行の処理をSUMXの内側に入れる
最低請求込み金額 =
SUMX(
Sales,
MAX(Sales[数量] * Sales[単価], 100)
)
これで「明細ごとに最低請求」を再現できます。
原因4:合計だけフィルターが外れている(ALL/REMOVEFILTERSの影響)
メジャーの中でALLやREMOVEFILTERSを使っていると、意図せず合計行だけが広い範囲で計算され、見た目の合計がズレることがあります。
例:前年差を取るために日付フィルターを外す、などはよくあるパターンです。
解決策:外したいフィルターと残したいフィルターを明確にする
「全部外す」のではなく、「この列だけ外す」や「この粒度は残す」を意識します。
-
全削除:REMOVEFILTERS(テーブル)
-
特定列だけ:REMOVEFILTERS(日付[日付])
-
一部だけ残す:ALLEXCEPT(テーブル, 残したい列…)
どれを使うべきかはモデル構造次第ですが、合計が不自然に見えるときは、まずフィルターを外し過ぎていないか疑います。
5. 合計ズレを直すための実践レシピ
ここからは、現場で使う「直し方の型」をまとめます。
レシピ1:まず“合計は何であるべきか”を言語化する
合計がズレるとき、最初に決めるべきなのはこれです。
-
合計は、表示されている行の足し算であるべきか
-
合計は、全体条件で再計算した値であるべきか
割合や平均は、多くのケースで2が自然です。
一方、端数処理や明細ルールがあるものは1が自然です。
ここが曖昧だと、DAXだけいじっても迷子になります。
レシピ2:合計を「表示行の足し算」に寄せる基本形
マトリクスの行に置いている列(粒度)で回すのが基本です。
合計を表示行の足し算に寄せる =
SUMX(
VALUES(行に置いているディメンション[列]),
[明細で表示しているメジャー]
)
-
行が部門なら部門でVALUES
-
行が商品なら商品でVALUES
-
行が得意先なら得意先でVALUES
これが一番事故が少ないです。
レシピ3:明細は通常ロジック、合計だけ積み上げロジックにする
明細では普通に計算して、合計だけSUMXで積み上げる、という作りがとても多いです。
指標_合計調整 =
IF(
ISINSCOPE(部門[部門名]),
[指標], -- 明細(部門行)ではそのまま
SUMX(VALUES(部門[部門名]), [指標]) -- 合計は部門単位で積み上げ
)
ISINSCOPEを使うと「今その列が行としてスコープに入っているか」を判定できます。
マトリクスで合計行だけ挙動を変えたいときに便利です。
レシピ4:SUMXの回す対象を“ファクト”から“ディメンション”へ寄せる
パフォーマンスの面でも、意味の面でも重要です。
-
Sales(明細)を回す:行数が多いほど重い。粒度が細かすぎて意図とズレやすい
-
部門・顧客・商品などを回す:行数が少ない。欲しい粒度を作りやすい
回す対象を変えるだけで、合計ズレが一気に直るケースが多いです。
6. デバッグのコツ:ズレの正体を見える化する
合計ズレは「どこで粒度が変わったのか」「どこでフィルターが外れたのか」が原因です。見える化すると直しやすくなります。
コツA:行数・ユニーク数を出す
明細行数 = COUNTROWS(Sales)
顧客数 = DISTINCTCOUNT(顧客[顧客ID])
商品数 = DISTINCTCOUNT(商品[商品ID])
合計行と明細行で、これらがどう変わるかを見ると、どの粒度で計算されているかの手がかりになります。
コツB:VARで途中結果を分ける
読みやすさとミス防止に効きます。
売上 =
VAR qty = SUM(Sales[数量])
VAR price = AVERAGE(Sales[単価])
RETURN
qty * price
この例はわざと危ない形です。数量合計×単価平均になり、明細の「数量×単価」の足し算とは一致しません。
こういうズレに気づきやすくなるのがVARの良さです。
7. よくある質問(合計ズレで詰まるポイント)
Q1. SUMXを使えば合計ズレは全部直る?
直りません。SUMXは「行ごとの計算を積み上げる」道具なので、そもそも合計が“再計算であるべき”指標(利益率など)にSUMXを当てると、意味が変わってしまいます。
合計がズレて見えるのではなく、合計の定義が違うだけ、というケースも多いです。
Q2. SUMXが遅い。どうすればいい?
よく効く対策は次の順です。
-
回す対象を明細からディメンションへ(VALUES(商品[商品ID])など)
-
余計なFILTERを多重に入れない
-
使い回せる計算はVARにする
-
そもそも列に存在するならSUMにする(SUMXを不要にしない)
SUMXは便利ですが、何百万行の明細を毎回なめるような書き方は重くなりがちです。
Q3. 計算列で作るのとメジャーで作るの、どっちがいい?
合計ズレの話に限っていえば、基本はメジャーで考えるのが安全です。
計算列はデータ更新時に固定され、フィルターやスライサーで動かせません。行ごとの固定値が必要なときは計算列、切り口で変わる値はメジャー、が基本です。
8. まとめ:SUMXの使いどころは「合計の定義」を守るため
SUMXなどのイテレーター関数は、ただの難しい関数ではありません。
「行ごとのルールを守ったまま合計したい」「表示行の結果を積み上げたい」という、現場の当たり前をPower BIで再現するための道具です。
最後に、判断の早見を置いておきます。
-
列をそのまま足せばよい → SUM
-
行ごとの計算式(掛け算、条件分岐、丸め)を積み上げたい → SUMX
-
合計を“再計算”ではなく“表示行の足し算”にしたい → VALUES(粒度) を回してSUMX
-
明細と合計でロジックを変えたい → ISINSCOPE + 合計だけSUMX
合計が合わないと感じたら、まず「合計は何を表すべきか」を決めて、次に「その粒度で回すには、どのテーブル(VALUES)を使うか」を選ぶ。これだけで、直せるケースが一気に増えます。
もし困り事があるなら、まずは無料相談を
「Power BI で箱ひげ図を使って詳細分析をしたいが、データモデルやDAX設計が複雑でわからない…」「Power Automate を併用してデータ更新フローを自動化したいが、どこから手を付ければいいのかわからない」といったお悩みをお持ちの方も多いのではないでしょうか。
私たちは、Power BIやPower AutomateなどのMicrosoft製品の導入・運用支援、およびデータ活用コンサルティングを行っています。
-
具体的な設定や開発代行
-
社内教育のための伴走型支援
-
有料プランへの移行タイミングやROIの判断支援
など、さまざまなニーズに合わせたサービスをご用意しています。まずはお気軽に「無料相談」へお申し込みください。下記のリンクからお問い合わせいただけます。
7. セミナーで学ぶ!DAX 関数の実践スキル
箱ひげ図をはじめ、Power BIを使いこなすうえで欠かせないのがDAX関数の知識です。DAXをしっかり学ぶことで、データの前処理から複雑な指標の算出までスムーズにこなせるようになります。そんなDAXとデータモデル設計を効率よく学習できるハンズオンセミナーを開催しています。
🔰 Power BIハンズオンセミナー初級編
-
短時間でデータモデリングの基礎を身につける
-
実務にすぐ活かせるレポート作成を実践形式で学ぶ
-
少人数制なので、つまずきポイントを都度フォロー
🚀 Power BIハンズオンセミナー中級編
-
DAX関数 × データモデル設計 の実践的なノウハウを習得
-
複雑な分析要件にも対応できる応用力を身につける
-
即戦力として業務効率アップや社内評価向上に直結
👉 詳細はこちら
DAXをしっかりマスターすると、箱ひげ図のような高度な可視化においても、必要なデータを柔軟に加工・集計できるようになります。結果的に、組織全体のデータドリブン化をリードできる存在となり、キャリアアップにも大いに役立ちます。
コメント