C#のLINQでJoinを使いこなす!データ結合の基本を徹底解説
生徒
「C#で複数のリストにあるデータを、共通の項目でつなぎ合わせて一つにまとめたいのですが、何か良い方法はありますか?」
先生
「それならLINQの『Join』という機能を使うのが一番ですよ。バラバラの情報を関連付けて、新しいデータとして取り出すことができます。」
生徒
「Join(ジョイン)ですか?難しそうに聞こえますが、初心者でも使えますか?」
先生
「大丈夫ですよ。図解や身近な例えを使って、一歩ずつ丁寧に解説していきますね。それでは見ていきましょう!」
1. LINQのJoin(データ結合)とは?
C#のプログラミングにおいて、LINQ(リンク)はデータ操作を劇的に楽にしてくれる魔法のような道具です。その中でも「Join」は、異なる二つのデータ群を、特定の「共通の鍵」を使ってガッチャンコと結合させる機能のことを指します。
例えば、あなたの手元に「社員の名簿」と「部署の名前リスト」があったとしましょう。社員の名簿には「どの部署に所属しているか」という番号だけが書いてあります。これだけでは、その社員が何部にいるのかパッと見て分かりませんよね?そこで、部署リストの番号と照らし合わせて、社員名と部署名をセットにして表示したくなるはずです。これが「データの結合(Join)」の役割です。
プログラミング未経験の方にとって、データが分かれている理由は少し不思議かもしれません。しかし、実際のシステムでは、情報を整理整頓して管理するために、名簿や商品リスト、注文履歴といった具合に、あえてデータを小分けにして保存するのが一般的なのです。これらを必要な時につなぎ合わせる技術こそが、今回学ぶJoinなのです。
2. Joinを使うための準備:用語解説
コードを書く前に、いくつか大切な用語を整理しておきましょう。これを知っておくと、この後の説明がずっとスムーズになります。
- コレクション: データの集まりのことです。C#ではリスト(List)などが代表的です。
- キー(Key): 二つのデータをつなぐための「共通の項目」です。先ほどの例では「部署番号」がこれにあたります。
- 外部シーケンス: 結合したい相手側のデータの集まりを指します。
- 匿名型: 結合した結果、新しく作った「名前のない一時的なデータ形式」のことです。
3. 実際にJoinを使ってみよう!
まずは、一番基本となる「内部結合(インナージョイン)」という方法を学びます。これは「両方のリストに共通して存在するデータだけを取り出す」というルールです。具体的なサンプルコードを見てみましょう。
サンプルプログラム:社員と部署を結合する
using System;
using System.Collections.Generic;
using System.Linq;
// 社員クラスの定義
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public int DepartmentId { get; set; }
}
// 部署クラスの定義
public class Department
{
public int Id { get; set; }
public string DeptName { get; set; }
}
public class Program
{
public static void Main()
{
// 1. 社員リストの作成
List<Employee> employees = new List<Employee>
{
new Employee { Id = 1, Name = "田中さん", DepartmentId = 10 },
new Employee { Id = 2, Name = "佐藤さん", DepartmentId = 20 },
new Employee { Id = 3, Name = "鈴木さん", DepartmentId = 10 }
};
// 2. 部署リストの作成
List<Department> departments = new List<Department>
{
new Department { Id = 10, DeptName = "営業部" },
new Department { Id = 20, DeptName = "開発部" }
};
// 3. LINQのJoinを使って結合!
var query = employees.Join(
departments, // 結合する相手
emp => emp.DepartmentId, // 自分側のキー(社員の部署ID)
dept => dept.Id, // 相手側のキー(部署のID)
(emp, dept) => new // 結果をどう作るか
{
EmployeeName = emp.Name,
DepartmentName = dept.DeptName
});
// 4. 結果を表示
foreach (var item in query)
{
Console.WriteLine($"{item.EmployeeName}さんは{item.DepartmentName}に所属しています。");
}
}
}
実行結果
田中さんは営業部に所属しています。
佐藤さんは開発部に所属しています。
鈴木さんは営業部に所属しています。
4. コードの内容をやさしく解説
今書いたプログラムの中で、特に重要な「Join」の部分を詳しく紐解いていきましょう。パソコンを触ったことがない方でもイメージしやすいように説明しますね。
employees.Join(...) という部分は、「社員名簿に対して、他のリストをくっつけますよ」という宣言です。括弧の中には4つの設定項目が入っています。
- 第一引数(departments): どのリストと合体させるかを指定します。ここでは「部署リスト」です。
- 第二引数(emp => emp.DepartmentId): 社員名簿のどの項目を使って探すかを決めます。社員が持っている「部署番号」ですね。
- 第三引数(dept => dept.Id): 部署リスト側のどの項目と一致させるかを決めます。部署リストの「ID」です。
- 第四引数((emp, dept) => new { ... }): 無事に合体できたとき、どんな形のデータにするかを決めます。ここでは「社員の名前」と「部署の名前」だけを抜き取って、新しいペアを作っています。
このように、「これとこれを、この番号が同じだったら、この形式で取り出して!」とお願いするのがJoinの仕組みです。非常に効率的で、一つ一つ手作業で探す必要がありません。
5. なぜJoinを使う必要があるの?
「最初から一つのリストに全部書いておけばいいじゃないか」と思うかもしれません。しかし、データが何万件、何十万件と増えてくると、そうはいきません。
もし「営業部」という名前が「セールス部」に変わったとします。一つのリストに全部書いていたら、何千人もの社員データの「営業部」という文字を書き直さなければなりません。これは大変な作業ですし、間違いも起きやすいです。
でも、データを分けて管理していれば、部署リストの「営業部」を「セールス部」に一箇所書き換えるだけで済みます。Joinを使えば、プログラムが実行される瞬間に最新の情報をガッチャンコしてくれるので、常に正確なデータが表示されるのです。これを専門用語でデータの正規化と呼びますが、今は「メンテナンスを楽にするための工夫」と覚えておけば十分です。
6. 複数の条件で結合する方法
時には、一つの番号だけでなく「名前と日付が両方一致したら結合したい」というような、複雑な条件が必要になることもあります。LINQのJoinでは、このようなケースにも対応可能です。複数の項目を組み合わせる場合は、new { ... } という形(匿名型)を使ってキーを作成します。
// 複数のキーで結合する例(イメージ)
var complexQuery = listA.Join(
listB,
a => new { a.FirstName, a.LastName }, // listAの姓名
b => new { b.FirstName, b.LastName }, // listBの姓名
(a, b) => new { a.Age, b.Job } // 一致したときの結果
);
このように書くことで、名字と名前の両方がぴったり合った人だけを紐付けることができます。初心者の方は、まずは「番号一つでつなげる方法」を完璧にマスターしてから、こうした応用法にチャレンジしてみてくださいね。
7. クエリ構文を使ったJoinの書き方
ここまで紹介したのは「メソッド構文」と呼ばれる書き方ですが、C#にはもう一つ「クエリ構文」という書き方があります。これはSQLというデータベース言語に似た書き方で、人によっては「こちらの方が読みやすい」と感じることもあります。
// クエリ構文でのJoin
var querySyntax = from emp in employees
join dept in departments on emp.DepartmentId equals dept.Id
select new
{
EmployeeName = emp.Name,
DepartmentName = dept.DeptName
};
on ... equals ... という部分が、先ほどの「どの項目同士をつなげるか」という指定に対応しています。C#のLINQでは、どちらの書き方を使っても同じ結果が得られます。自分の好みや、チームの開発ルールに合わせて使い分けられるようになると、C#プログラマーとして一歩前進です。
8. 注意点:データが見つからない場合
Joinを使う上で気をつけておきたいのが、「相手側のデータが見つからない時」の挙動です。今回解説した通常のJoin(内部結合)では、もし社員名簿に「存在しない部署番号(例:99番)」を持っている人がいた場合、その社員の情報は結果に表示されません。合体相手がいないので、無視されてしまうのです。
「相手がいなくても、とりあえず社員だけは表示したい!」という場合には、また別の手法(GroupJoinなど)が必要になりますが、まずは基本のJoinを使いこなし、「共通点があるもの同士をくっつける」という感覚を身につけることが大切です。
9. 学習のポイント:手を動かしてみよう
プログラミング学習において、最も早く上達する方法は「自分でコードを書いて、わざと間違えてみること」です。今回のサンプルコードを使って、次のようなことを試してみてください。
- 新しい社員を一人追加してみる。
- 部署の名前を変えてみる。
- 結合の結果に「社員のID」も表示されるように作り直してみる。
パソコンの操作に不慣れなうちは、アルファベットの綴りを一つ間違えるだけでエラーが出て、嫌になってしまうこともあるかもしれません。しかし、エラーは「ここを直せば動くよ!」というコンピュータからの親切なヒントです。一つずつ解決していくうちに、LINQの強力なデータ操作能力があなたの手になじんでくるはずです。
C#のLINQを使ったデータの結合は、システム開発の現場で毎日のように使われる非常に重要な技術です。Joinをマスターすることで、バラバラだったデータが意味のある「情報」へと変わる瞬間を体験できるでしょう。焦らずに、まずはシンプルなデータの合体から楽しんでみてください。