SUMMARIZE関数の研究～集計列の追加はなぜ非推奨なのか🤔～

# はじめに

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

本記事は`SUMMARIZE`関数編です。

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

続きものです。

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)

## 参考記事

参考…というかほぼパクリ検証ですので、基本的にはSQLBIの下記記事を読むのをおすすめします😁

https://www.sqlbi.com/articles/all-the-secrets-of-summarize/

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

## `SUMMARIZE`関数の文法を調べる

DAX GUIDEで`SUMMARIZE`関数の文法を確認します。

https://dax.guide/summarize/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/129fed99-203e-be4f-1854-736dd1eae052.png)

ベーステーブルを最初に指定して、その後はグループ化したい列名を入れていきます。またその後、<Name>,<Expression>では集計列を追加することができます。

#### 非推奨…？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/8c140a14-3a00-db9e-9918-1acea2b78aac.png)

しかしその下の説明文を読むと、パラメーターの`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 }
    }
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/cc694fdb-d3d4-933b-fc82-fcb5ce7f3e42.png)


## `SUMMARIZE`関数で集計列を追加してみる

非推奨だとは言われていますが、どうやら、できる。
列を集計することはできており、数字も正しい🤔

```
SUMMARIZE(
    Sales_Single_Table,
    Sales_Single_Table[カラー],
    "売上", SUM(Sales_Single_Table[売上])
    )
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/36d04649-736d-acd8-0809-07a53231a8ce.png)

# フィルターを操作してみる

そこで、今度はフィルターを操作して全体の売上を表示する列を作成してみます。
結果の期待値としては、こう。
**割合を求めるとき**にはこういう列をつくるときありますよね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/31f7e493-7270-4c79-099a-9884d6e307cc.png)

方針としては`REMOVEFILTERS`関数を使用して、カラー列でかかっている行コンテキストを削除し、**合計値1,800**を求めていきます。

https://dax.guide/removefilters

方針通り、DAXを記載して実行すると…

```
SUMMARIZE (
    Sales_Single_Table,
    Sales_Single_Table[カラー],
    "売上", SUM ( Sales_Single_Table[売上] ),
    "総売上",
        CALCULATE (
            SUM ( Sales_Single_Table[売上] ),
            REMOVEFILTERS ( Sales_Single_Table[カラー] )
        )
)
```

結果は、こう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/3c8071f4-f107-6724-9797-ff90faeb5f85.png)

むむ？期待した結果と違う🤔**500という数字はどこからきた？**

どういう処理がなされているのか検証する旅にでます。まず、プロダクト列を追加して、結果をもう少し細かく見てみます。

```
SUMMARIZE (
    Sales_Single_Table,
    Sales_Single_Table[カラー],
    Sales_Single_Table[プロダクト],
    "売上", SUM ( Sales_Single_Table[売上] ),
    "総売上",
        CALCULATE (
            SUM ( Sales_Single_Table[売上] ),
            REMOVEFILTERS ( Sales_Single_Table[カラー] )
        )
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/a71fece3-d295-d40f-d03e-f3cfb2de5103.png)

やはり売上列と総売上列の数字は合わない。

## `SUMMARIZE`関数はクラスターを作成する。

参考にした記事をさらに読むと、`SUMMARIZE`関数は**クラスター**を作成する…とあります。

引数で指定した列がクラスターヘッダーとなります。
クラスターはクラスターヘッダーを先頭に、テーブル内すべての列を使って作成されます。
そして各クラスターの中で集計し、結果のテーブルが出力されます。

図解すると下記のような感じの計算が行われているらしい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/acbd2b70-4533-e047-3125-5e516545060d.png)

ということを前提に、`REMOVEFILTERS`関数を用いたDAXを書いたときに何が起こっているのか図解してみます。

```
SUMMARIZE (
    Sales_Single_Table,
    Sales_Single_Table[カラー],
    "総売上",
        CALCULATE (
            SUM ( Sales_Single_Table[売上] ),
            REMOVEFILTERS ( Sales_Single_Table[カラー] )
        )
)
```

1. 元のテーブル
1. 引数[カラー]列を先頭にクラスターが作られる
1. `REMOVEFILTERS`関数によりカラー列のフィルターが解除される

という動きをして、`レッド`を先頭に作成されたクラスターは

- (“バイク”,1,100)
- (“シャツ”,2,200)

という２つのフィルターコンテキストをもとに売上列の集計を始めます。

すると、

- (“シャツ”,2,200)

は`グリーン`クラスターで作成されたクラスターの中にも同じコンテキストの数字があります。

ということで、図で囲んだ赤枠部分をすべて足し上げて、レッドの総売上は**500**という数字になってしまいます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/2fccc9ba-d013-1abe-e830-d42b5b17c588.png)

# ややこしい

直感的ではない計算方法になってしまうので、ややこしく、計算ミスの温床になってしまいそう。


# ではどうしたらいいのか🤔

今、求めたい数字を出すためには、すべての列のフィルターを解除してあげれば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 )
        )
)
```

結果は期待した数字になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/781d41a9-38d8-d428-86cc-02dff1394615.png)

# この検証はシングルテーブルだということを忘れちゃだめ

`REMOVEFILTERS`関数の引数にテーブルを指定してあげればいいってこと？という解釈はしないほうがよくて、現在の検証は列もすくなく、行も少ない、シングルテーブルで行っています。実際には複数テーブルがあり、リレーションシップで構成されたデータモデルがあるはずです。その場合はさきほどのクラスター作成がより複雑になり、より直感的ではなくなります。

**ということで…**

# `SUMMARIZE`関数のベストプラクティス

**列のグループ化にだけ使うこと！**

集計列を`SUMMARIZE`関数で追加しようとすると、前述したクラスターが作成されてからの動きをよーく考える必要がでてきて、直感的ではない記述をする必要があります。ですので、`SUMMARIZE`関数は列のグループ化のみに使用しましょう。

# じゃあ集計列の追加はどうすればいいの…？🤔

`ADDCOLOMNS`関数研究記事に続く👍

# 参考資料

https://qiita.com/PowerBIxyz/items/aa61bdfae8adf5dc06b7

https://www.sqlbi.com/articles/all-the-secrets-of-summarize/

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

https://www.sqlbi.com/articles/introducing-summarizecolumns/

https://learn.microsoft.com/ja-jp/dax/summarize-function-dax

https://learn.microsoft.com/ja-jp/dax/addcolumns-function-dax

https://learn.microsoft.com/ja-jp/dax/summarizecolumns-function-dax