【Power Query】キーの型がバラバラで結合できない時の対処法

Power Queryで型不一致キーを正規化してから結合するコード例(ハイライト行はTrimmed = "" の判定) Power Query

困った場面

Power Queryで2つのテーブルを、社員コードのような共通キーで結合(マージ)したときに、一部の行だけ相手側の情報が空欄になることがあります。

キーの値を見比べても、片方は「123」、もう片方も「123」で、同じに見えます。それでも一致しません。

原因は見た目ではなく型です。同じ意味のキーでも、取得元のシステムによってstring型(文字列)とnumeric型(数値)が混在していることがあります。Power Queryの結合は値の型まで見て一致を判定するため、表示上は同じでも型が違うと不一致扱いになります。

解決コード

結合する前に、両方のキーを同じ型・同じ表記に正規化します。ここでは文字列に統一する例です。

// 正規化関数
NormalizeKey = (key as any) as text =>
    let
        Str     = Text.From(key),
        Trimmed = Text.TrimStart(Str, "0")
    in
        if Trimmed = "" then "0" else Trimmed

結合したい各テーブルに、正規化済みのキー列を追加してからマージします。

// 各テーブルに正規化済みのキー列を追加する例
let
    Source = SourceTable,
    Added  = Table.AddColumn(Source, "Key_Normalized", each NormalizeKey([EmployeeCode]), type text)
in
    Added

これを両方のテーブルに適用し、元のキー列ではなく「Key_Normalized」列同士で結合します。実際に詳細エディターへ貼り付けて実行した例が次の画面です。

Power QueryのNormalizeKey関数と結合処理を貼り付けた詳細エディター画面(構文エラーなし)

正規化した「Key_Normalized」列同士で結合した結果です。型が違っていた3件とも、Department列に正しい値が入っています。

NormalizeKeyで正規化した結果、EmployeeCodeの型が違うテーブル同士でもDepartment列が正しく結合された例

解説

Power Queryの結合は、表示上の見た目ではなく値の型まで見て一致を判定します。片方がstring型の「123」、もう片方がnumeric型の123だと、そのままでは一致しません。

型が混在する原因は、取得元システムの違いです。同じ意味のキーでも、あるシステムからのエクスポートはstring型、別のシステムからのエクスポートはnumeric型になる、ということが起こります。

対処は「結合する前に、両方とも同じ型・同じ表記にそろえる」ことです。今回の例ではText.Fromで数値も文字列に変換し、Text.TrimStartで先頭ゼロを取り除いて表記をそろえています。結合にはTable.NestedJoinを使っています。

正規化した列は、元のキー列とは別の新しい列として追加しています。元の列を残しておくと、あとから見直すときに元データとの対応が分かりやすくなります。

キーの全桁が0のケース(例:「00000」と0)は、先頭ゼロを全部取り除くと空文字になってしまいます。そのため、空文字になった場合だけ「0」を返すようにしています。実際に試したところ、この分岐がないと全桁0のキーだけ一致しなくなることを確認しています。

JSONから取り込んだ値で、同じ項目の文字列と数値が混在する場合は、【Power Query】JSONの型ゆれ|文字列と数値の混在を吸収するも参照してください。時刻の値が9時間ズレる場合は、【Power Query】時刻が9時間ズレる原因とタイムゾーン変換で扱っています。

型はそろっているのに、結合した後で行が増える場合は、【Power Query】結合で行が増える原因と重複の検知方法で扱っています。

まとめ

  • Power Queryの結合は型まで見て一致を判定するため、見た目が同じでも型が違うと一致しない
  • 結合前に正規化関数で型と表記をそろえる
  • 全桁が0のような特殊なキーにも対応しておく

コメント

タイトルとURLをコピーしました