Power Platformを使い始めた人が最初に止まる場所がある。Dataverseにテーブルを作ってExcelデータを流し込んだのに、Lookup列が空のままになる。SQLで慣れているなら「JOINすれば取れる」と思うが、DataverseのLookupはそういう仕組みではない。

結論を先に言う。DataverseのLookup列は、クエリ実行時に別テーブルを動的に結合するものではなく、各レコードに参照先の識別子をあらかじめ保存しておく設計だ。 この発想の違いを補正しないまま進むと、Excelインポートのたびに参照が空になり、Power Automateで取得したレコードにLookupの情報が入らない謎に何度もぶつかる。


SQLのJOINと何が違うのか

SQLのJOIN(テーブル結合)は、SELECTを実行する瞬間に「この列が一致するレコードを取ってくる」という処理をその場で走らせる。物理的なテーブル構造には何も追加されず、クエリを書いた人間が結合条件を都度指定する。

DataverseのLookup列は動きが根本的に違う。

観点SQL JOINDataverse Lookup
結合のタイミングクエリ実行時(動的)データ保存時(事前)
保存される値なし(結合条件のみ)参照先レコードのGUID
設計の主役SELECTを書く人テーブルを設計する人
参照先が変わったときクエリを書き直す各レコードの値を更新する

Lookup列を作成すると、Dataverseは2つのテーブル間にN:1(多対1)のリレーションシップを自動で生成する(出典:Microsoft Learn「Create a relationship between tables by using a lookup column」)。そして子テーブルの各レコードには、親テーブルの該当レコードを指すGUID(グローバル一意識別子:システムが自動生成する長い文字列の一意ID)が物理的に保存される。

ExcelのVLOOKUP(ブイルックアップ)と混同している場合も注意が必要だ。VLOOKUPはセルを参照するときに都度計算する。DataverseのLookupは計算ではなく保存だ。


Excelインポートで参照が空のままになる理由

Excelインポートは「フラットな行データをDataverseに流し込む」操作にすぎない。ここでのポイントは、Lookup列に必要なのは表示名ではなく参照先レコードのGUIDだということだ。

Excelのセルには「株式会社◯◯」「田中太郎」などの表示名が入っている。Dataverseはその表示名から自動でGUIDを解決する機能を持たない。インポートの時点で「どのレコードのGUID」かが確定していないため、Lookup列は空のまま保存される。これはDataverseの欠陥ではなく設計の原則だ。


機能させるために必要な2段階

Lookup列を使いこなすには、作業を2段階に分けて考える必要がある。

段階1:テーブル間のLookup列を定義する(設計フェーズ)

Power AppsのMaker Portalで、子テーブル(参照する側)にLookup列を追加する。この操作でN:1リレーションシップが自動生成され、「このテーブルは別のテーブルを参照できる構造になった」という状態になる。

段階2:各レコードに参照先を実際に入れる(データ投入フェーズ)

構造を作っただけでは、各レコードのLookup列はまだ空だ。そこに参照先GUIDを入れる操作が別途必要になる。

SQL経験者がつまずくのはここだ。SQLではSELECT * FROM 注文 JOIN 顧客 ON ...と書けば、テーブルに追加保存しなくても結合した結果が得られる。Dataverseは違う。「構造を作る」と「値を入れる」は別の工程であり、設計後にデータを流し込む手順が必要になる。


Dataflowsで参照を自動解決する

参照を入れる手段としてDataflows(データフロー)が使える。DataflowsはExcelインポートと異なり、取り込み時に「この列の値が一致する親テーブルのレコードを探して、そのGUIDをLookup列にセットする」処理ができる(出典:Microsoft Learn「Mapping fields with relationships in standard dataflows」)。

ただし、そのためには**Alternate Key(代替キー:業務コードやメールアドレスなど、GUIDの代わりにレコードを一意に特定できる別の列)**の設定が先に必要だ。

Dataflowsのセットアップ手順

1. 親テーブルにAlternate Keyを設定する

Power AppsのMaker Portalで親テーブルを開き、「Keys」タブからAlternate Keyを追加する。業務上の一意値(顧客コード、メールアドレスなど)を持つ列を選ぶ。1テーブルに最大10個まで定義できる(出典:Microsoft Learn「Define alternate keys to reference rows with Microsoft Dataverse」)。NULL値を含む列に設定すると一意制約が適用されないため、値が必ず入る列を選ぶこと。

2. 親テーブルのDataflowを先に実行する

子テーブルのLookup列に参照をセットするには、参照先の親テーブルのレコードがDataverse内にすでに存在していなければならない。親テーブルのDataflowを先に走らせてから、子テーブルのDataflowを実行する。この順序を逆にすると参照が解決できず、Lookup列が空のままになる(出典:Microsoft Learn「Mapping fields with relationships in standard dataflows」)。

3. 子テーブルのDataflowマッピングでLookup列を選ぶ

Alternate Key設定後、子テーブルのDataflowマッピング画面にLookup列が表示されるようになる。マッピング画面でLookup列が出てこない場合、ほぼ確実に親テーブルのAlternate Keyが未設定だ。

なお、Dataflowsのマッピングはポリモーフィック(多態型:1つのLookup列が複数の異なるテーブルを参照できる特殊な構造)のLookup列には現在対応していない。


フラットテーブルだけで管理するとどうなるか

Lookup列を使わずに、すべての情報を1つのテーブルにフラットに持つ設計を選ぶと別の問題が生まれる。

たとえば顧客名、住所、担当者名を含む注文テーブルをフラットに作った場合、同じ顧客の注文が10件あれば顧客名や住所が10行に重複する。顧客の住所が変わったとき、10行すべてを更新しなければならない。更新漏れが出た時点で、データとしての整合性が崩れる。

Dataverse のLookup設計は、この問題を「顧客テーブルと注文テーブルを分けて、注文テーブルには顧客テーブルへの参照だけ持たせる」という構造で解消する(出典:Microsoft Learn「Create a relationship between tables by using a lookup column」——Lookup列=N:1リレーションシップの設計意図として公式ドキュメントで確認)。顧客情報は1か所で管理され、変更があれば参照先を1件更新するだけで済む。


Dataverse でのSQL JOINは使えるのか

技術的には使える。DataverseはTDS(SQL)エンドポイントをサポートしており、SQLクエリを実行できる。ただし、SELECT *やJOIN、NESTED FROMを含むクエリはサーバー負荷を理由にタイムアウトが自動的に2分に短縮される(通常のタイムアウトは5分)。公式の説明は「these queries put too much pressure on the server」(これらのクエリはサーバーに過大な負荷をかける)だ(出典:Microsoft Learn「How Dataverse SQL Differs from Transact-SQL」)。

DataverseはSQLの動的JOIN前提で使うことを想定していない。Lookup列による事前保存参照が、Dataverseにとってのリレーションシップの正規の使い方だ。


M365 Developer Tenantで試す

ここまでの設計を手を動かしながら確かめるには、本番環境を使わずに検証できる場所があると早い。Microsoft 365 Developer Program(マイクロソフト365 デベロッパープログラム)は無料でDataverse環境を含むPower Platformをフル利用できる検証テナント(独立した環境)を提供している。

Alternate Keyの設定、親テーブル先行実行、子テーブルのDataflowマッピングの挙動は、概念として読むより一度手を動かしてみた方が理解が早い。

→ 関連記事:Alternate Keyを使ったDataverseへの安全なUpsert(更新または新規追加)手順


まとめ

DataverseのLookup列はSQLのJOINではなく、各レコードに参照先GUIDを事前保存する設計だ。Excelインポートで参照が空のまま残るのはこの構造が原因で、対処には親テーブルへのAlternate Key設定とDataflowsの実行順序管理が必要になる。


次の一歩:Power AppsのMaker Portal(make.powerapps.com、無料)でテーブルを1つ作り、Lookup列を追加してN:1リレーションシップが自動生成される動きを確認する。次に親テーブルのKeysタブを開き、Alternate Keyを追加してみる。この2操作だけで、今回の設計の根幹が体感できる。

関連記事