はじめに
すこし複雑なメジャーを記述しようとすると、避けては通れないテーブル操作関数中でも主要なSUMMARIZE
、ADDCOLOMNS
、 SUMMARIZECOLUMNS
などを研究してみます。
本記事はSUMMARIZE
関数編です。
テーブル操作関数シリーズ
続きものです。
- SUMMARIZE関数の研究~集計列の追加はなぜ非推奨なのか🤔~
- ADDCOLUMNS関数の研究~集計列追加のベストプラクティス🤔~
- 集計列追加のベストプラクティス🤔~とはいえ例外だってあるぞ~
- SUMMARIZECOLUMNS関数の研究~SUMMARIZE関数は非推奨?🤔~
- GROUPBY関数の研究🤔~基本動作確認編~
参考記事
参考…というかほぼパクリ検証ですので、基本的にはSQLBIの下記記事を読むのをおすすめします😁
SUMMARIZE
関数の文法を調べる
DAX GUIDEでSUMMARIZE
関数の文法を確認します。
ベーステーブルを最初に指定して、その後はグループ化したい列名を入れていきます。またその後、,では集計列を追加することができます。
非推奨…?
しかしその下の説明文を読むと、パラメーターのName
とExpression
のところには NOT RECOMMENDED(非推奨) と書いてあります。
なぜだ🤔
検証開始
使用データ
Power BI Desktopの「New Table」で下記DAXを入力。
簡単なテーブルを作成し、検証していきます。
Sales_Single_Table =
DATATABLE (
"プロダクト", STRING,
"カラー", STRING,
"数量", INTEGER,
"売上", DOUBLE,
{
{ "バイク", "レッド", 1, 100 },
{ "シャツ", "レッド", 2, 200 },
{ "シャツ", "グリーン", 2, 200 },
{ "バイク", "グリーン", 3, 300 },
{ "シャツ", "グリーン", 3, 300 },
{ "バイク", "ブルー", 3, 300 },
{ "シャツ", "ブルー", 4, 400 }
}
)
SUMMARIZE
関数で集計列を追加してみる
非推奨だとは言われていますが、どうやら、できる。
列を集計することはできており、数字も正しい🤔
SUMMARIZE(
Sales_Single_Table,
Sales_Single_Table[カラー],
"売上", SUM(Sales_Single_Table[売上])
)
フィルターを操作してみる
そこで、今度はフィルターを操作して全体の売上を表示する列を作成してみます。
結果の期待値としては、こう。
割合を求めるときにはこういう列をつくるときありますよね。
方針としてはREMOVEFILTERS
関数を使用して、カラー列でかかっている行コンテキストを削除し、合計値1,800を求めていきます。
方針通り、DAXを記載して実行すると…
SUMMARIZE (
Sales_Single_Table,
Sales_Single_Table[カラー],
"売上", SUM ( Sales_Single_Table[売上] ),
"総売上",
CALCULATE (
SUM ( Sales_Single_Table[売上] ),
REMOVEFILTERS ( Sales_Single_Table[カラー] )
)
)
結果は、こう。
むむ?期待した結果と違う🤔500という数字はどこからきた?
どういう処理がなされているのか検証する旅にでます。まず、プロダクト列を追加して、結果をもう少し細かく見てみます。
SUMMARIZE (
Sales_Single_Table,
Sales_Single_Table[カラー],
Sales_Single_Table[プロダクト],
"売上", SUM ( Sales_Single_Table[売上] ),
"総売上",
CALCULATE (
SUM ( Sales_Single_Table[売上] ),
REMOVEFILTERS ( Sales_Single_Table[カラー] )
)
)
やはり売上列と総売上列の数字は合わない。
SUMMARIZE
関数はクラスターを作成する。
参考にした記事をさらに読むと、SUMMARIZE
関数はクラスターを作成する…とあります。
引数で指定した列がクラスターヘッダーとなります。
クラスターはクラスターヘッダーを先頭に、テーブル内すべての列を使って作成されます。
そして各クラスターの中で集計し、結果のテーブルが出力されます。
図解すると下記のような感じの計算が行われているらしい。
ということを前提に、REMOVEFILTERS
関数を用いたDAXを書いたときに何が起こっているのか図解してみます。
SUMMARIZE (
Sales_Single_Table,
Sales_Single_Table[カラー],
"総売上",
CALCULATE (
SUM ( Sales_Single_Table[売上] ),
REMOVEFILTERS ( Sales_Single_Table[カラー] )
)
)
- 元のテーブル
- 引数[カラー]列を先頭にクラスターが作られる
-
REMOVEFILTERS
関数によりカラー列のフィルターが解除される
という動きをして、レッド
を先頭に作成されたクラスターは
- (“バイク”,1,100)
- (“シャツ”,2,200)
という2つのフィルターコンテキストをもとに売上列の集計を始めます。
すると、
- (“シャツ”,2,200)
はグリーン
クラスターで作成されたクラスターの中にも同じコンテキストの数字があります。
ということで、図で囲んだ赤枠部分をすべて足し上げて、レッドの総売上は500という数字になってしまいます。
ややこしい
直感的ではない計算方法になってしまうので、ややこしく、計算ミスの温床になってしまいそう。
ではどうしたらいいのか🤔
今、求めたい数字を出すためには、すべての列のフィルターを解除してあげればOKというわけです。
SUMMARIZE (
Sales_Single_Table,
Sales_Single_Table[カラー],
"総売上",
CALCULATE (
SUM ( Sales_Single_Table[売上] ),
REMOVEFILTERS (
Sales_Single_Table[カラー],
Sales_Single_Table[プロダクト],
Sales_Single_Table[数量],
Sales_Single_Table[売上]
)
)
)
REMOVEFILTERS
関数ですべての列を指定する場合は、テーブル名だけ書いてあげれば同じ意味になります。
SUMMARIZE (
Sales_Single_Table,
Sales_Single_Table[カラー],
"総売上",
CALCULATE (
SUM ( Sales_Single_Table[売上] ),
REMOVEFILTERS ( Sales_Single_Table )
)
)
結果は期待した数字になりました。
この検証はシングルテーブルだということを忘れちゃだめ
REMOVEFILTERS
関数の引数にテーブルを指定してあげればいいってこと?という解釈はしないほうがよくて、現在の検証は列もすくなく、行も少ない、シングルテーブルで行っています。実際には複数テーブルがあり、リレーションシップで構成されたデータモデルがあるはずです。その場合はさきほどのクラスター作成がより複雑になり、より直感的ではなくなります。
ということで…
SUMMARIZE
関数のベストプラクティス
列のグループ化にだけ使うこと!
集計列をSUMMARIZE
関数で追加しようとすると、前述したクラスターが作成されてからの動きをよーく考える必要がでてきて、直感的ではない記述をする必要があります。ですので、SUMMARIZE
関数は列のグループ化のみに使用しましょう。
じゃあ集計列の追加はどうすればいいの…?🤔
ADDCOLOMNS
関数研究記事に続く👍
参考資料