Power BIのレポートを作っていると、「行の値はそれっぽいのに、合計行だけ数字が合わない」「マトリクスの合計が、表示されている行を足した結果にならない」といった現象に必ずぶつかります。これはバグではなく、DAXがそういう考え方で計算するからです。
そのうえで、合計がズレる問題を正しく直す鍵が、SUMXに代表されるイテレーター関数です。power bi dax iterator という言葉で調べる人が多いのも、まさにここがつまずきポイントだからです。
この記事では、SUMXなどを「いつ使うべきか」「なぜ合計がズレるのか」「どう直すのが筋が良いのか」を、できるだけ噛み砕いて整理します。
1. まず結論:合計がズレる一番の理由
DAXのメジャーは、ビジュアルの各セル(各行)で一度ずつ計算されます。そして合計行も、「各行の結果を足し算」しているのではなく、合計行のフィルター条件でメジャーをもう一回計算しています。
つまりこうです。
この仕組みのせいで、次のような計算はズレやすくなります。
-
割合(利益率、構成比、達成率)
-
平均(平均単価、平均日次、平均処理時間)
-
何かを丸めてから合計する計算
-
条件分岐で行ごとに計算式が変わるもの
そして、行ごとの計算を意図どおり積み上げたいときに登場するのがSUMXです。
2. SUMとSUMXは何が違うのか(超重要)
SUM:列をそのまま足す
SUMは「ある列の値を、そのまま合計」します。
SUMX:テーブルを1行ずつ回して、式を評価して足す
SUMXは「指定したテーブルを1行ずつ見て、各行で式を計算して、それを合計」します。
イメージはこうです。
-
1行目を取り出す
-
式を計算する
-
結果を足し込む
-
次の行へ…を最後まで繰り返す
例えば、売上金額が列として存在しない(単価と数量しかない)場合。
SUMではできない「行単位の計算→合計」ができる。これが基本の使いどころです。
3. イテレーター関数を使うべき典型パターン
パターンA:行単位の掛け算・引き算・条件分岐がある
以下はSUMX向きです。
例:明細単位で丸めてから合計する(合計後に丸めるのとは結果がズレることがあります)
パターンB:割合や平均を「表示行の足し算」で合計したい
利益率のような指標は、合計行が「全体の利益÷全体の売上」になりがちです。これは多くの場合、正しい集計です。
ただし、業務要件として「各部門の利益率を足した数」を合計として見せたい、というような要望が出ることがあります(会計的には変ですが、報告上そうしたい場面がある)。
そのときは、合計行で「表示行の粒度」を明示して回す必要があり、SUMXが役に立ちます。
パターンC:同じメジャーでも、明細と合計で粒度を切り替えたい
マトリクスでよくあるのがこれです。
-
行(明細):その行の計算ロジック
-
合計:明細の結果を足し上げるロジック
この「合計だけ別ロジック」は、DAXでは普通にやります。むしろ、やらないとビジネスで欲しい形にならないことが多いです。
4. 合計が合わない代表例と、ズレ方の正体
ここからが本題です。合計がズレる原因を、よくある形で分解します。
原因1:合計行は「足し算」ではなく「再計算」だから
例:利益率
この利益率を、部門別に表示するとこうなります。
-
部門A:Aの利益率
-
部門B:Bの利益率
-
合計:全社の利益率(全社利益÷全社売上)
合計が「部門Aの利益率 + 部門Bの利益率」にならないのは当たり前です。合計は「全体条件で再計算」されているからです。
解決策:合計で“どの粒度を足すのか”を決める
もし合計を「表示されている部門ごとの利益率の足し算」に寄せたいなら、こうします。
ポイントは、SUMXで回す対象を Sales のような明細テーブルにしないことです。ここで欲しいのは「部門ごとの1行」なので、VALUES(部門[部門名]) のように、粒度を固定して回します。
原因2:SUMXで回している粒度がズレている(回し過ぎ・回さな過ぎ)
SUMXは強力ですが、「どのテーブルを回すか」で結果が変わります。
例えば、顧客別の売上を並べたビジュアルで、合計が二重計上っぽくなる場合があります。これは、
という違いがそのまま結果に出るからです。
よくある悪い例(明細を回してしまう)
「顧客ごとの売上を足したい」のに、Salesを回すと、想定より細かい単位で計算してしまうことがあります。
解決策:回す対象は“欲しい粒度”に合わせる
顧客単位で積み上げたいなら、顧客で回します。
製品単位なら製品、店舗単位なら店舗。合計が欲しい粒度に合わせて、VALUESやSUMMARIZEで“回す単位”を作るのがコツです。
原因3:丸めや最低保証など、行ごとに処理してから足したいのに、合計で一括処理している
例:1明細ごとに最低請求100円、のようなルール。
-
明細ごとに MAX(計算結果, 100) をして合計したい
-
でも合計側で MAX(全体, 100) をしてしまうと意味が変わる
解決策:行の処理をSUMXの内側に入れる
これで「明細ごとに最低請求」を再現できます。
原因4:合計だけフィルターが外れている(ALL/REMOVEFILTERSの影響)
メジャーの中でALLやREMOVEFILTERSを使っていると、意図せず合計行だけが広い範囲で計算され、見た目の合計がズレることがあります。
例:前年差を取るために日付フィルターを外す、などはよくあるパターンです。
解決策:外したいフィルターと残したいフィルターを明確にする
「全部外す」のではなく、「この列だけ外す」や「この粒度は残す」を意識します。
どれを使うべきかはモデル構造次第ですが、合計が不自然に見えるときは、まずフィルターを外し過ぎていないか疑います。
5. 合計ズレを直すための実践レシピ
ここからは、現場で使う「直し方の型」をまとめます。
レシピ1:まず“合計は何であるべきか”を言語化する
合計がズレるとき、最初に決めるべきなのはこれです。
-
合計は、表示されている行の足し算であるべきか
-
合計は、全体条件で再計算した値であるべきか
割合や平均は、多くのケースで2が自然です。
一方、端数処理や明細ルールがあるものは1が自然です。
ここが曖昧だと、DAXだけいじっても迷子になります。
レシピ2:合計を「表示行の足し算」に寄せる基本形
マトリクスの行に置いている列(粒度)で回すのが基本です。
-
行が部門なら部門でVALUES
-
行が商品なら商品でVALUES
-
行が得意先なら得意先でVALUES
これが一番事故が少ないです。
レシピ3:明細は通常ロジック、合計だけ積み上げロジックにする
明細では普通に計算して、合計だけSUMXで積み上げる、という作りがとても多いです。
ISINSCOPEを使うと「今その列が行としてスコープに入っているか」を判定できます。
マトリクスで合計行だけ挙動を変えたいときに便利です。
レシピ4:SUMXの回す対象を“ファクト”から“ディメンション”へ寄せる
パフォーマンスの面でも、意味の面でも重要です。
回す対象を変えるだけで、合計ズレが一気に直るケースが多いです。
6. デバッグのコツ:ズレの正体を見える化する
合計ズレは「どこで粒度が変わったのか」「どこでフィルターが外れたのか」が原因です。見える化すると直しやすくなります。
コツA:行数・ユニーク数を出す
合計行と明細行で、これらがどう変わるかを見ると、どの粒度で計算されているかの手がかりになります。
コツB:VARで途中結果を分ける
読みやすさとミス防止に効きます。
この例はわざと危ない形です。数量合計×単価平均になり、明細の「数量×単価」の足し算とは一致しません。
こういうズレに気づきやすくなるのがVARの良さです。
7. よくある質問(合計ズレで詰まるポイント)
Q1. SUMXを使えば合計ズレは全部直る?
直りません。SUMXは「行ごとの計算を積み上げる」道具なので、そもそも合計が“再計算であるべき”指標(利益率など)にSUMXを当てると、意味が変わってしまいます。
合計がズレて見えるのではなく、合計の定義が違うだけ、というケースも多いです。
Q2. SUMXが遅い。どうすればいい?
よく効く対策は次の順です。
SUMXは便利ですが、何百万行の明細を毎回なめるような書き方は重くなりがちです。
Q3. 計算列で作るのとメジャーで作るの、どっちがいい?
合計ズレの話に限っていえば、基本はメジャーで考えるのが安全です。
計算列はデータ更新時に固定され、フィルターやスライサーで動かせません。行ごとの固定値が必要なときは計算列、切り口で変わる値はメジャー、が基本です。
8. まとめ:SUMXの使いどころは「合計の定義」を守るため
SUMXなどのイテレーター関数は、ただの難しい関数ではありません。
「行ごとのルールを守ったまま合計したい」「表示行の結果を積み上げたい」という、現場の当たり前をPower BIで再現するための道具です。
最後に、判断の早見を置いておきます。
-
列をそのまま足せばよい → SUM
-
行ごとの計算式(掛け算、条件分岐、丸め)を積み上げたい → SUMX
-
合計を“再計算”ではなく“表示行の足し算”にしたい → VALUES(粒度) を回してSUMX
-
明細と合計でロジックを変えたい → ISINSCOPE + 合計だけSUMX
合計が合わないと感じたら、まず「合計は何を表すべきか」を決めて、次に「その粒度で回すには、どのテーブル(VALUES)を使うか」を選ぶ。これだけで、直せるケースが一気に増えます。
コメント