集計列追加のベストプラクティス🤔～とはいえ例外だってあるぞ～

# はじめに

すこし複雑なメジャーを記述しようとすると、避けては通れないテーブル操作関数。主要な`SUMMARIZE`、`ADDCOLUMNS`、 `SUMMARIZECOLUMNS`などを研究してみます。

**テーブル操作関数シリーズ**

続きものです。

1. [SUMMARIZE関数の研究～集計列の追加はなぜ非推奨なのか🤔～](https://qiita.com/akihiro_suto/items/a317d560fd298403bc15)
1. [ADDCOLUMNS関数の研究～集計列追加のベストプラクティス🤔～](https://qiita.com/akihiro_suto/items/ced4c9053f11fbe2baf3)
1. [集計列追加のベストプラクティス🤔～とはいえ例外だってあるぞ～](https://qiita.com/akihiro_suto/items/331aee0734b98c0ec345)
1. [SUMMARIZECOLUMNS関数の研究～SUMMARIZE関数は非推奨?🤔～](https://qiita.com/akihiro_suto/items/1a7c08aaf369ee1cc3a3)
1. [GROUPBY関数の研究🤔～基本動作確認編～](https://qiita.com/akihiro_suto/items/aaf2e4c98cf88833dc63)

## DAXクエリ＆DAX.do

https://dax.do/

今回の検証はDAX.do上でDAXクエリを書いて検証していきます。
DAXクエリがわからない方は先にこの記事を読んで、DAX.doで少し触ってからのほうが理解が進むでしょう。

DAXクエリについてはこちらの記事を参照してください。

https://qiita.com/hanaseleb/items/96b80210a7fc20c36a13

# 参考記事

https://www.sqlbi.com/articles/best-practices-using-summarize-and-addcolumns/

# 復習

集計列追加のベストプラクティス

```
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] ) )
)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/0eb8c683-38f3-02ba-398e-b9009a11df0d.png)

# 例外を検証してみる

参考記事をもとにDAXを実行してみます。`GENERATE`関数と`TOPN`関数で各製品ごとに売上上位２名の売上金額を集計しています。これはフィルターコンテキストを操作していませんし、正しい数字が計算されています。

```
EVALUATE
SUMMARIZE (
    GENERATE ( 'Product', TOPN ( 2, Customer, [Sales Amount] ) ),
    'Product'[Category],
    Customer[Country],
    "Margin", [Margin]
)
ORDER BY [Margin] DESC
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/4dc7141d-a0b1-7dcc-be43-529bf8a9a609.png)

## 集計列追加のベストプラクティスを適用してみる🤔

上記DAXの集計列部分をベストプラクティスに沿って`ADDCOLUMNS`関数を追加してみます。

```
EVALUATE
ADDCOLUMNS (
    SUMMARIZE (
        GENERATE ( 'Product', TOPN ( 2, Customer, [Sales Amount] ) ),
        'Product'[Category],
        Customer[Country]
    ),
    "Margin", [Margin]
)
ORDER BY [Margin] DESC
```

すると結果は先程よりも大きい数字が得られ、計算結果が期待した数字ではありません🤔

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/14cb740a-b6b4-697f-e65c-f2cee2379fae.png)

参考記事を読むに、`SUMMARIZE`関数の中で計算している**製品ごとの売上上位２名の売上金額**が`ADDCOLUMNS`関数でくるんだときに、集系列に対して適切にフィルターコンテキストが伝わらないことが原因のよう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/b5e2139d-2ddf-c13c-4b25-1145803735b2.png)

ということは🤔いま出た結果は`SUMMARIZE`関数の中で計算しているものをなくしたものと結果が合うはず。`GENERATE`関数以下の部分を削除し、'Sales'テーブルに置き換え、DAXクエリを実行してみます。

```
EVALUATE
ADDCOLUMNS (
    SUMMARIZE (
        'Sales',
        'Product'[Category],
        Customer[Country]
    ),
    "Margin", [Margin]
)
ORDER BY [Margin] DESC
```

ベストプラクティスを適用したときと同様の数字を得ることができました。やはり、`SUMMARIZE`関数の元テーブルで計算したフィルターコンテキストが`ADDCOLUMNS`関数で追加した集計列に届いていません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/e713cf4e-14fc-f711-8aa3-ff4006b41e2a.png)

## 正しい結果にするには💪

`SUMMARIZE`関数の中で計算している**製品ごとの売上上位２名の売上金額**を変数で定義します。そして、`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
```

すると、ようやく正しい数字がでました💪 ただ…**ややこしい！**
参考記事によるとパフォーマンスも良くないらしい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/e0dd77de-4ae4-5247-7a45-11ef06b28adb.png)

# 集計列追加のベストプラクティスの例外

**集計列追加のベストプラクティスの例外**

`SUMMARIZE`関数で追加した集計列を`ADDCOLUMNS`関数に置き換えないほうがいいときは、

- `SUMMARIZE`関数で使用されるテーブルに特定のフィルターがある場合
- 集計列で、メジャーなど`SUMMARIZE`関数でまとめたテーブルにない項目を使用するとき

ということ。（だと理解した。）

**うーむ難しい🤔**

# まとめ

手を動かしながら検証をしていくと理解が進む。記事を読んだだけじゃあわからない。だけど、正しく理解ができているのか、正しく言語化できているのか自信がない😅
少しでも興味をもってくれた人は参考記事も必ず読んでくださいね！

# 改めて参考記事

https://www.sqlbi.com/articles/best-practices-using-summarize-and-addcolumns/