doodle-on-web

自分で調べたことや、仕事の中で質問されたことなどをまとめています。

VLOOKUPの限界を超える|INDEX・MATCHでテーブル結合する方法【左参照・複数条件も対応】

スポンサーリンク


あなたもこんな経験はありませんか?

「VLOOKUPで別シートのデータを引っ張りたいのに、参照したい列が左側にある…」 「列を追加したら数式が全部ズレて、修正に1時間かかった…」

Excelやスプレッドシートを使っていると、VLOOKUPの壁に何度もぶつかります。そのたびに「もっとスマートな方法があるはずだ」と感じているなら、この記事はまさにあなたのためのものです。

この記事でわかること: - INDEX・MATCHの基本的な仕組みと書き方 - 2つのテーブルを実務データで結合する具体的な手順 - 複数条件を使った高度な結合方法


まず確認:なぜINDEX・MATCHなのか

学習を始める前に、「なぜわざわざVLOOKUPを卒業する必要があるのか」を整理しておきましょう。

比較項目 VLOOKUP INDEX・MATCH
左側の列を参照 ✕ できない ✓ 自由に参照可
列追加への耐性 弱い(数式が壊れる) 強い(範囲指定のため)
複数条件での検索 困難 配列数式で対応可
大量データの処理 やや重い 効率的
習得難易度 易しい やや高い

VLOOKUPは「検索列の右側にあるデータしか取れない」という構造的な制約があります。一方、INDEX・MATCHは検索範囲と取得範囲を独立して指定するため、左右・上下を問わずどの列からでも値を取得できます。列を追加・削除しても数式が壊れない点も、実務では大きなメリットです。


INDEX・MATCHの仕組みを理解する

MATCHの役割:「何行目?」を調べる

=MATCH(検索値, 検索範囲, 照合の種類)

MATCH は、指定した値が配列の何番目にあるか(行番号)を返します。第3引数の 0 は完全一致を意味します。

=MATCH("C003", A2:A6, 0)  → 3(C003は3行目にある)

INDEXの役割:「その位置の値を返す」

=INDEX(配列, 行番号, [列番号])

INDEX は、指定した範囲の特定の位置にある値を返します。

=INDEX(B2:B6, 3)  → B列の3番目の値を返す

2つを組み合わせると:

=INDEX(返したい列, MATCH(検索値, 検索する列, 0))

「MATCHで何番目かを調べ、その番号をINDEXに渡す」というシンプルな連携です。これだけ理解できれば、基本的なテーブル結合は問題なく実装できます。


実践:2つのテーブルを結合する

使用するテーブル

テーブルA(注文データ)

注文ID 顧客ID 金額
001 C003 5,000
002 C001 3,200
003 C002 8,800
004 C005 1,500
005 C004 6,700

テーブルB(顧客マスタ)

顧客ID 顧客名 地域
C001 佐藤 東京
C002 鈴木 大阪
C003 高橋 名古屋
C004 田中 福岡
C005 伊藤 札幌

やりたいこと: 注文データに「顧客名」と「地域」を結合する(SQLの LEFT JOIN に相当)

顧客名を取得する数式(D列)

=INDEX(テーブルB!$B$2:$B$6, MATCH(B2, テーブルB!$A$2:$A$6, 0))

数式の読み方: 1. MATCH(B2, テーブルB!$A$2:$A$6, 0) → 注文データの顧客ID(例:C003)が顧客マスタの何行目にあるかを返す 2. INDEX(テーブルB!$B$2:$B$6, ...) → その行番号を使って顧客名列から値を取得する

D2に入力したら、D3〜D6にコピーします。$(絶対参照)がついているため、コピーしても参照範囲はズレません。

地域を取得する数式(E列)

=INDEX(テーブルB!$C$2:$C$6, MATCH(B2, テーブルB!$A$2:$A$6, 0))

INDEX の参照先を地域列(C列)に変えるだけです。MATCH 部分は共通して使い回せます。

結合後のテーブルA

注文ID 顧客ID 金額 顧客名 地域
001 C003 5,000 高橋 名古屋
002 C001 3,200 佐藤 東京
003 C002 8,800 鈴木 大阪
004 C005 1,500 伊藤 札幌
005 C004 6,700 田中 福岡

応用:複数条件でテーブルを結合する

「顧客IDが同じでも年度によってデータが異なる」場合など、2つ以上のキーで一致させたいケースがあります。

使用するテーブル

テーブルB′(年度別顧客マスタ)

顧客ID 年度 担当者
C001 2023 山田
C001 2024 中村
C002 2023 小林
C002 2024 加藤
C003 2024 渡辺

やりたいこと: 顧客ID かつ 年度が一致する担当者名を取得する

複数条件のMATCH数式

=INDEX(テーブルB′!$C$2:$C$6,
  MATCH(1,
    (テーブルB′!$A$2:$A$6=B2)*(テーブルB′!$B$2:$B$6=C2),
  0))

Excelの場合: Ctrl + Shift + Enter で配列数式として確定 Google スプレッドシートの場合: 通常の Enter で動作

仕組みの解説: - (A列=条件1)`(B列=条件2) はそれぞれ TRUE/FALSE の配列を返す - *(掛け算)で AND 条件を表現(両方 TRUE のとき 1、それ以外は 0) - MATCH(1, ..., 0) で「1になっている行(=両方一致する行)」を探す

SQLで言えば ON A.顧客ID = B.顧客ID AND A.年度 = B.年度 に相当します。


よくあるエラーと対処法

#N/A エラーが出る

原因: 検索値がテーブルBに存在しない(マスタに登録されていないIDなど)

対処: IFERROR でラップして、エラー時の表示を制御する

=IFERROR(INDEX(テーブルB!$B$2:$B$6, MATCH(B2, テーブルB!$A$2:$A$6, 0)), "未登録")

正しくない値が返ってくる

原因: データ型の不一致。例えば検索値が数値なのに、マスタ側が文字列で格納されているケース

対処: TEXT()VALUE() で型を統一する

=MATCH(TEXT(B2, "000"), テーブルB!$A$2:$A$6, 0)

注文IDが 001 のように0埋めされている場合は特に注意が必要です。


まとめ

INDEX・MATCHは最初こそ「なぜ2つの関数を組み合わせるの?」と感じるかもしれません。しかし一度仕組みを理解すると、VLOOKUPでは対応できない多くの場面で頼れる武器になります。

今日から試せる3ステップ: 1. まず基本形 =INDEX(..., MATCH(..., ..., 0)) を1つ書いてみる 2. 絶対参照($)をつけて、数式を下にコピーする 3. IFERROR でエラー処理を追加して完成

実務のスプレッドシートにある既存のVLOOKUP数式を、INDEX・MATCHに書き換えてみるのが一番の近道です。ぜひ今日から試してみてください。