はじめに
はじめまして。ATLのヴィリアスです。
Power BI初心者の私が、DAXのCount系関数で悩みまくり、
Microsoft Docsを読んでもよく分からなかったため、色々検証してみました。
備忘録として、私が学んだことをここに残します。
※この記事は、Power BIでの動作がメインです。
※免責事項(必ず、ご一読ください)
本記事の情報により生じた、いかなる損害や損失についても、当社は一切の責任を負いかねます。
また、誤情報が入り込んだり、情報が古くなったりすることもありますので、
必ずしも正確性を保証するものではありません。ご了承ください。
検証に使うテーブル
Count系関数の検証にあたって、次の2つのテーブルをExcelで用意しました。
テーブル名: 各社の在庫
会社 | 製品 | 在庫数 |
---|---|---|
〇〇社 | マウス | 1 |
〇〇社 | モニター | 3 |
✕✕社 | マウス | 10 |
○✕社 | (空文字) | 1 |
△△社 | キーボード | 3 |
△△社 | ヘッドホン | |
□□社 | 0 | |
□□社 | マウス | 3000 |
□□社 | モニター |
テーブル名: ブール
No | ブール値 |
---|---|
1 | True |
2 | False |
3 | False |
4 | True |
5 | True |
Count系関数の一覧
まず最初に、Count系関数は8種類あります。
関数 | 説明 |
---|---|
Count |
値 (数値, 日付, 文字列) が入っている行数をカウント。 空文字もカウントする。 空白はカウントしない。 ブール値はカウントできない。 実はCountXの簡易版。 |
CountA |
Count All 空白ではない行数をすべてカウント。 空文字、ブール値もカウントする。 |
CountX |
Count Expression Countの色々できる版。 値 (数値, 日付, 文字列) が入っている行数をカウント。 第1引数にテーブルを取る。(フィルターしたテーブルなどを使うのが基本) 第2引数に式(列)を取る。 空白はカウントしない。 ブール値はカウントできない。 |
CountAX |
Count All Expression CountAとCountXが合体したもの。 |
CountRows | テーブルの行数を数える。空白もカウント。 |
CountBlank | 列の空白をカウント。空文字もカウント。 |
DistinctCount | 重複した値は加算せずにカウント。 空白と空文字は別としてカウント。 |
DistinctCountNoBlank | 重複した値は加算せずにカウント。 空白はカウントしない。 空文字はカウント。 |
Count, CountA, CountX, CountAX の4つの違いが理解できれば、もう何も怖くないです。
では、それぞれ見ていきましょう。
Count
基本中の基本、Count
です。
これは、 値 (数値, 日付, 文字列(空文字も含む)) をカウントします。
空白はカウントしません。
また、ブール値に対してCount
を使うとエラーになります。
まず [在庫数] をカウントしたい場合は、次のように記述します。
/* COUNT(<列>) */
Count = COUNT('各社の在庫'[在庫数])
結果
全9行のうち、空白はカウントせずに在庫数が記入されている 7行 をしっかりカウントできていますね。
では次に 空文字がカウントされるか、[製品] で確認します。
Count = COUNT('各社の在庫'[製品])
結果
○✕社の [製品] は空文字ですが、しっかりカウントされて結果は 8 になりました。
では、ブール値にCount
を使うとどうなるのか。
エラーが出ます。
以下、エラーメッセージの一部です。
メジャー 'ブール'[Count] での計算エラー: 関数 COUNT は、数値または日付に評価される引数を受け取ります。型 Boolean の値は操作できません。
「ブール値をカウントしたいよ!」という場合は、次のCountA
を使います。
CountA (Count All)
CountA
は Count All です。すべて(All)をカウントします。
CountA
は、Count
とほぼ変わりません。(Power BIでは)
ただ先ほども言ったように、CountA
は True や False のブール値をカウントすることができます。
/* COUNTA(<列>) */
CountA = COUNTA('ブール'[ブール値])
##CountAの補足
ちなみに、Excelに絡めてCount
とCountA
の違いを厳密に言うと、
まずCountA
は対象列のセルの型に、数値やら文字列やらが混ざっていても、何でもカウントできます。
一方でCount
は数値のカウントがメインとなるため、文字列が混ざるとそれはカウントされません。
次のExcelのスクリーンショットを見てください。
C4 と D4 にはそれぞれ、Count
とCountA
を使って A2:A7 をカウントした値が入っています。
そして、 A2:A7 には「1, 2, 3, 6」の数値と「四, 五」の文字列が入っています。
Count
は数値のカウントがメインであるため、「四, 五」の文字列はカウントしません。したがって結果は 4 となります。
CountA
は何でもカウントするため、数値だろうが文字列だろうが関係ありません。結果は 6 です。
ではなぜ冒頭で私は、
CountA
は、Count
とほぼ変わりません。(Power BIでは)
と言ったのか。
それはPower BIでは、列の型は1つに決定されるからです。
Excelでは、列の各セルに対して任意の型を設定できます。(例: A列の1行目の型は文字列、2行目は数値、3行目は文字列)
しかし、Power BIではそれができないのです。
1列目の型を数値とすれば1列目の全行の型が数値になりますし、文字列とすれば文字列になります。
つまりPower BIでは1列の中に色々な型が存在することがないため、
ブール値を除けばCountA
もCount
も同じように値をカウントできます。
そのため、「CountA
とCount
はほぼ変わらない」としています。
CountX (Count Expression)
CountX
は Count Expression です。式(Expression)を使ってカウントします。
CountX
は、第1引数にテーブルを、第2引数に式(というか列)を取ります。
例えば、'各社の在庫' テーブルの [在庫数] をカウントする場合、次のように記述します。
/* COUNTX(<テーブル>, <式>) */
CountX = COUNTX('各社の在庫', '各社の在庫'[在庫数])
この結果、ついさっき見た覚えがありませんか?
実はこれ、Count
で [在庫数] をカウントしているのと変わらないんですよね。
「じゃあ、Count
でいいじゃん。なんでCountX
が存在するの?」
その答えはCountX
の 第1引数は、FILTERなどで加工したテーブルを取ることができるからです。
例えば「'各社の在庫' テーブルの中で、在庫数が10以上の製品をカウントしたいよ!」というときは、次のように記述します。
CountX = COUNTX(FILTER('各社の在庫', '各社の在庫'[在庫数]>=10), '各社の在庫'[製品])
結果
第1引数で**「在庫数が10以上」にフィルターされるテーブルを取っています。
そして「在庫数が10以上」なのは、✕✕社のマウスと□□社のマウスであるため、結果は 2 となります。
このようにCountX
は、Count
よりも高度なカウントができます。**
もちろんCount
と同様、空文字もカウントできます。
CountX = COUNTX(FILTER('各社の在庫', '各社の在庫'[在庫数]==1), '各社の在庫'[製品])
結果
○✕社の [製品] は空文字ですが、カウントできています。
CountAX (Count All Expression)
CountAX
は Count All Expression です。すべて(All)を式(Expression)を使ってカウントします。
CountAX
は、CountA
とCountX
が合体したものです。
そのため、第1引数にフィルター済みテーブルを取ったり、ブール値をカウントしたりすることができます。
/* COUNTAX(<テーブル>, <式>) */
CountAX = COUNTAX(FILTER('ブール', 'ブール'[No]<=3), 'ブール'[ブール値])
結果
ここでは「Noが3以下」にフィルターしているため、結果は 3 となります。
その他についてはCountA
とCountX
で説明しているので省略します。
CountRows
CountRows
はテーブルの行数(Rows)をカウントします。
/* COUTROWS([<テーブル>]) */
CountRows = COUNTROWS('各社の在庫')
簡単ですね!
また、引数が空でも大丈夫です。
その場合、メジャーが存在するテーブル(ホームテーブル)の行数がカウントされます。
CountRows = COUNTROWS()
このように、メジャーCountRows
は 'ブール' テーブル下にあるため、引数をなしにすると 'ブール' テーブルの行数 5 を取得できます。
CountBlank
CountBlank
は空白(Blank)をカウントします。空文字もカウントします。
/* COUNTBLANK(<列>) */
CountBlank = COUNTBLANK('各社の在庫'[製品])
結果
○✕社の空文字も、□□社の空白もカウントし、結果は 2 になりました。
DistinctCount
DistinctCount
は重複する値を加算せず(Distinct)にカウントします。
空白と空文字は 別物 としてカウントされます。
/* DISTINCTCOUNT(<列>) */
DistinctCount = DISTINCTCOUNT('各社の在庫'[製品])
結果
[製品] には「マウス, モニター, キーボード, ヘッドホン」の4つに加えて、空文字と空白の2つがあります。
したがって、結果は 6 となります。
重複する値が1つとしてカウントされているのが分かりますね。
DistinctCountNoBlank
DistinctCountNoBlank
はDistinctCount
が空白を無視(NoBlank)するようにしたものです。
空文字は無視されません。
/* DISTINCTCOUNTNOBLANK(<列>)*/
DistinctCountNoBlank = DISTINCTCOUNTNOBLANK('各社の在庫'[製品])
結果
DistinctCount
では 6 でしたが、DistinctCountNoBlank
は□□社の空白を無視するため 5 となります。
また、○✕社の空文字は無視されていないのも確認できます。
#おわりに
自分なりにCount系関数をまとめてみましたが、いかがだったでしょうか。
この記事が、私と同じように悩んでいる方の助けになれば幸いです。
それではまた、次の記事で。