QlikのNull問題 〜第1回 そのIsNull大丈夫?〜

こんにちは!Yokoです。
担当しているプロジェクトで、CSVファイルで連携されてくるデータを取り込んでいるんだけど、「Nullを表示しない」と設定してもチャートに表示されちゃうんですよ。
これは空文字で連携されているからそういうことになっちゃうんですけどね…
たちが悪いのは、同じファイルにNullになる項目と空文字になる項目があったりして、おそらくCSV作成のクエリに問題があるんだろうと思うけど、これらを意識せずに万能に対処したいよね。

また、他の人が作成したスクリプトを見てて、Where Not IsNull()…っていうのもよく見かけるんだけど、「これ、本当に大丈夫?」と思うこともしばしばあります。
ということで、今回はNullや空文字をQlikのロードスクリプトで正しく扱う方法を解説していきます。

目次

見た目で値がないデータのきほんのき

見た目データがないように見える値は、以下のパターンがあります。

呼び方意味区別
Null値が存在しない、未定義値が割り当てられていない状態で、Joinした時に該当する値がない場合などに発生します。
空文字長さが0の文字列データは存在していますが、中身が入っていない状態です。
空白文字半角スペース(” “)や全角スペース(”” )、タブ文字( \t )などの目に見えないスペース文字。長さは1以上あり、実際には「スペース」というデータが存在している状態です。

空白文字は別として、Nullと空文字はちょっと区別しにくいですよね。
SQLを使う人なら常識なんですが、

  • 長さ0の文字列って、値が存在しないんじゃないの?
  • 該当がないっていう値は長さ0の値なんじゃないの?

みたいな禅問答に陥ってしまう人もいるかもしれません😂
簡単にいいますと、アンケートに回答するとして、「なし」と回答した状態が空文字、見落として未記入のまま提出した状態がNullです。Nullは答えたのかどうかもわからない、データそのものが欠損しえいる状態っていうこと。

これでわからないと言われると、僕も禅問答に陥ってしまうので、これくらいで勘弁して下さい😅
(実際にデータを見たほうがわかります)

Nullと空文字データを作って比較してみる

QlikのロードスクリプトでNullと空文字、空白文字の値を生成しています。

TBL:
Load * Inline [
商品コード,売上
1,100
2,200
];

sales:
Load
	1 as 区分No,
	'会員' as 区分,
    'ライナー' as 会員名,
	商品コード,
    売上
Resident TBL;

Load
	2 as 区分No,
	'NULL' as 区分,
    Null() as 会員名,
	商品コード,
    売上
Resident TBL;

Load
	3 as 区分No,
	'空文字' as 区分,
    '' as 会員名,
	商品コード,
    売上
Resident TBL;

Load
	4 as 区分No,
	'空白文字' as 区分,
    ' ' as 会員名,  //半角スペース
	商品コード,
    売上
Resident TBL;

リロードすると以下のような結果になりました。
会員名で値をセットしたのですがNullの時は、-になり、空文字と空白文字は見た目では区別できません。
このデータを使って、会員別売上を集計してみましょう。
これもまた、空文字と空白文字の区別ができない状態になり…
あっちこっちのデータを使ってデータモデリングした時になんかでは、チャートを作ってみて初めて、「なんじゃこりゃ」ってなるのもよくあることです。

Nullだろうが空文字だろうが、無いものは無いとみなすスクリプトの書き方

予め、ロードスクリプトで会員名のある人は会員、それ以外はゲストという区分をつけたいというケース。
ここからは、スペースを意図的に入れた空白文字を除いて説明していきます。

■ IsNullを使った場合

以下のスクリプトを実行すると…

sales2:
Load *,
	If(Not IsNull(会員名), '会員', 'ゲスト') as 会員区分
Resident sales
;

Drop Table sales;

こんなふうに空文字は会員になってしまいます。
これって、期待通りの結果にはなっていません。
元データにNullが含まれているのか、空文字が含まれているのかをいちいち確認するのは面倒なので、空文字を会員とみなしてしまうのはミスリードになってしまいます。
もし、空文字のデータがたくさんある場合、空文字という会員がとてつもないヘヴィユーザとして集計されちゃうんですよね。気づかずに1人の会員として集計しているかも?

■ Len関数を使った場合

では、以下のスクリプトではどうなるでしょう。

sales2:
Load *,
	If(Len(会員名) > 0, '会員', 'ゲスト') as 会員区分
Resident sales
;

Drop Table sales;

結果はこうなりました。
Len(会員名) > 0を使うと、Nullも空文字も「ゲスト」として判定してくれます。

以上からわかるのは、Len関数を使用すれば、Nullも空文字も元データを確認する必要なく、万能に機能してくれるっていうことです。
なので、冒頭書いた、Where Not IsNull()… でWhere句を書いた時、もしかすると空文字が誤って取り込まれている可能性があるんですよね。
Where Not IsNull()…でスクリプトを買いている人、要チェックですよ!

因みに、空白文字(スペース)が混じっている可能性があるのなら、
If(Len(Trim(会員名)) > 0, ‘会員’, ‘ゲスト’) as 会員区分
とすればOKです。
空白文字は余りないと思うので、そこまでやる必要はないと思いますが、空白文字が混在する可能性があると思ったら、Trimも組み合わせてみて下さい。

まとめ

元データの値がNullなのか空文字なのかわからない場合のロードスクリプトの正しい書き方をご紹介しました。ポイントは…

Nullも空文字も意識せずに扱う場合のポイント

  • IsNull関数を使うと、空文字の値を識別できていない(大丈夫?)
  • Len関数はNullも空文字も0として扱える

以上、IsNullを何気なく使っている人は、念のためにご確認を!

ではまた!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

目次