あなたもこんな経験はありませんか?
「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に書き換えてみるのが一番の近道です。ぜひ今日から試してみてください。