はじめに
すこし複雑なメジャーを記述しようとすると、避けては通れないテーブル操作関数。主要なSUMMARIZE
、ADDCOLUMNS
、 SUMMARIZECOLUMNS
などを研究してみます。
テーブル操作関数シリーズ
続きものです。
- SUMMARIZE関数の研究~集計列の追加はなぜ非推奨なのか🤔~
- ADDCOLUMNS関数の研究~集計列追加のベストプラクティス🤔~
- 集計列追加のベストプラクティス🤔~とはいえ例外だってあるぞ~
- SUMMARIZECOLUMNS関数の研究~SUMMARIZE関数は非推奨?🤔~
- GROUPBY関数の研究🤔~基本動作確認編~
DAXクエリ&DAX.do
今回の検証はDAX.do上でDAXクエリを書いて検証していきます。
DAXクエリがわからない方は先にこの記事を読んで、DAX.doで少し触ってからのほうが理解が進むでしょう。
DAXクエリについてはこちらの記事を参照してください。
参考記事
復習
集計列追加のベストプラクティス
ADDCOLUMNS(
SUMMARIZE( <table>, <group by column> ),
<column_name>, CALCULATE( <expression> )
)
DAX.doで例を作成すると、こんな感じ。
EVALUATE
ADDCOLUMNS (
SUMMARIZE ( Sales, 'Product'[Brand] ),
"SalesAMT", CALCULATE ( SUMX ( 'Sales', Sales[Net Price] * Sales[Quantity] ) )
)
例外を検証してみる
参考記事をもとにDAXを実行してみます。GENERATE
関数とTOPN
関数で各製品ごとに売上上位2名の売上金額を集計しています。これはフィルターコンテキストを操作していませんし、正しい数字が計算されています。
EVALUATE
SUMMARIZE (
GENERATE ( 'Product', TOPN ( 2, Customer, [Sales Amount] ) ),
'Product'[Category],
Customer[Country],
"Margin", [Margin]
)
ORDER BY [Margin] DESC
集計列追加のベストプラクティスを適用してみる🤔
上記DAXの集計列部分をベストプラクティスに沿ってADDCOLUMNS
関数を追加してみます。
EVALUATE
ADDCOLUMNS (
SUMMARIZE (
GENERATE ( 'Product', TOPN ( 2, Customer, [Sales Amount] ) ),
'Product'[Category],
Customer[Country]
),
"Margin", [Margin]
)
ORDER BY [Margin] DESC
すると結果は先程よりも大きい数字が得られ、計算結果が期待した数字ではありません🤔
参考記事を読むに、SUMMARIZE
関数の中で計算している製品ごとの売上上位2名の売上金額がADDCOLUMNS
関数でくるんだときに、集系列に対して適切にフィルターコンテキストが伝わらないことが原因のよう。
ということは🤔いま出た結果はSUMMARIZE
関数の中で計算しているものをなくしたものと結果が合うはず。GENERATE
関数以下の部分を削除し、'Sales'テーブルに置き換え、DAXクエリを実行してみます。
EVALUATE
ADDCOLUMNS (
SUMMARIZE (
'Sales',
'Product'[Category],
Customer[Country]
),
"Margin", [Margin]
)
ORDER BY [Margin] DESC
ベストプラクティスを適用したときと同様の数字を得ることができました。やはり、SUMMARIZE
関数の元テーブルで計算したフィルターコンテキストがADDCOLUMNS
関数で追加した集計列に届いていません。
正しい結果にするには💪
SUMMARIZE
関数の中で計算している製品ごとの売上上位2名の売上金額を変数で定義します。そして、ADDCOLUMNS
関数で集計列を追加する際に、CALCULATE
関数でくくり、KEEPFILTERS
関数でフィルターコンテキストを保持して[Margin]メジャーの評価時に使用します。
DEFINE
VAR __producttop2customer =
GENERATE ( 'Product', TOPN ( 2, Customer, [Sales Amount] ) )
EVALUATE
ADDCOLUMNS (
SUMMARIZE ( __producttop2customer, Product[Category], Customer[Country] ),
"Margin", CALCULATE ( [Margin], KEEPFILTERS ( __producttop2customer ) )
)
ORDER BY [Margin] DESC
すると、ようやく正しい数字がでました💪 ただ…ややこしい!
参考記事によるとパフォーマンスも良くないらしい。
集計列追加のベストプラクティスの例外
集計列追加のベストプラクティスの例外
SUMMARIZE
関数で追加した集計列をADDCOLUMNS
関数に置き換えないほうがいいときは、
-
SUMMARIZE
関数で使用されるテーブルに特定のフィルターがある場合 - 集計列で、メジャーなど
SUMMARIZE
関数でまとめたテーブルにない項目を使用するとき
ということ。(だと理解した。)
うーむ難しい🤔
まとめ
手を動かしながら検証をしていくと理解が進む。記事を読んだだけじゃあわからない。だけど、正しく理解ができているのか、正しく言語化できているのか自信がない😅
少しでも興味をもってくれた人は参考記事も必ず読んでくださいね!
改めて参考記事