困った場面
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」列同士で結合します。実際に詳細エディターへ貼り付けて実行した例が次の画面です。

正規化した「Key_Normalized」列同士で結合した結果です。型が違っていた3件とも、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のような特殊なキーにも対応しておく


コメント