h.yamada/ 2023年 11月 7日/ 技術

ヤマダです。
本日はQlikのロードスクリプトにハマったので備忘録として投稿します。
前にもヤラかしたんですけど、構文エラーにならないので見事に忘れてました。

今回の事象

イメージとしてはトランザクションにマスタを結合する場合です。

売上:
Load * Inline [
顧客コード,金額
    A10,1000
    B10,2000
    C20,3000
    B10,2000
    D30,1500
];

Left Join
Load Distinct * Inline [
顧客コード,顧客名
    A10,ヤマダ
    B10,タナカ
    C20,タカハシ
    D30,サトウ
    B10,タナカ
];

ロードすると以下になります。

顧客コード 顧客名 金額
A10 ヤマダ 1000
B10 タナカ 2000
C20 タカハシ 2000
D30 サトウ 1500

なんとB10のレコードが1件欠落してしまうのです。
トランザクションに全項目が同じレコードが2件以上ある場合にこの事象が発生します。
これ仕様のようですね。。。
Left join with distinct

対応方法

今回の例ではそもそもマスタにレコードが重複していることが問題なのですが、データ界隈では往々としてよくあることです。
対応策として3種類考えてみました。
・DisinctとJoinを分ける
・1次的にトランザクションにUNIQUE項目を追加
・Mapping Loadを使用

DisinctとJoinを分ける

DistinctをLoadを別々に処理することで対応できます。

売上:
Load * Inline [
顧客コード,金額
    A10,1000
    B10,2000
    C20,3000
    B10,2000
    D30,1500
];

tmp:
Load Distinct * Inline [
顧客コード,顧客名
    A10,ヤマダ
    B10,タナカ
    C20,タカハシ
    D30,サトウ
    B10,タナカ
];

Left Join(売上)
Load * Resident tmp;
Drop table tmp;

1次的にトランザクションにUNIQUE項目を追加

今回はデータをInline Loadしているので、先行ロード(Preceding LOAD)でRowNoを使用しておりますが、CSV、QVDでLoadする場合はRowNoを項目追加すれば問題ありません。

売上:
Load
     *,
     RowNo() as SEQ
     ;
Load * Inline [
顧客コード,金額
    A10,1000
    B10,2000
    C20,3000
    B10,2000
    D30,1500
];

Left Join(売上)
Load Distinct * Inline [
顧客コード,顧客名
    A10,ヤマダ
    B10,タナカ
    C20,タカハシ
    D30,サトウ
    B10,タナカ
];

Drop Field SEQ From 売上;

Mapping Loadを使用

Mapping関数で事前にDistinct Loadをしておき、ApplyMapで値を追加します。今回もの売上をInline Loadしているので先行ロードを使用しております。

顧客:
Mapping Load Distinct * Inline [
顧客コード,顧客名
    A10,ヤマダ
    B10,タナカ
    C20,タカハシ
    D30,サトウ
    B10,タナカ
];

売上:
Load
    *,
    ApplyMap('顧客',顧客コード) as 顧客名
    ;
Load * Inline [
顧客コード,金額
    A10,1000
    B10,2000
    C20,3000
    B10,2000
    D30,1500
];

最後に

データ件数が多いとLoadが1つ増えるだけで処理時間に影響がありますので、適宜ご検討ください。よいQlikライフを!

About h.yamada

初めに触ったBIはPentaho、QlikView約10年、特にQlikを使用した基盤構築やってます。 Tableau Desktop Certified Associateの資格も持ってました(有効期限切れ)