Go言語の複雑なクエリ(JOIN)を構造体でマッピングする方法をやさしく解説
生徒
「Go言語でデータベースを使っているんですが、JOINを使ったらデータの受け取り方が分からなくなりました」
先生
「JOINは少し難しく感じますよね。でも構造体を使えば、整理して受け取れます」
生徒
「複数のテーブルのデータを、ちゃんと構造体に入れられるんですか?」
先生
「はい。順番と意味を理解すれば、とても分かりやすくなりますよ」
1. JOINとは何か
JOINとは、複数のテーブルをつなぎ合わせてデータを取得する方法です。
テーブルとは、表のように情報を整理して保存する箱のことです。
例えば「ユーザー情報」と「注文情報」が別々の表にある場合、それらを関連付けて一覧で見たいときにJOINを使います。
2. JOINを使うと何が難しくなるのか
JOINを使うと、取得する列の数が増えます。
その結果、Go言語でデータを受け取るときに、どの値が何なのか分からなくなりがちです。
これは、複数の箱の中身が一度に届いて、仕分けが追いつかない状態に似ています。
3. 構造体でデータを整理する考え方
Go言語では、構造体を使うことでデータをひとまとめにできます。
構造体とは、関連するデータを一つのセットとして扱う仕組みです。
JOINで取得した結果も、構造体にきちんと対応させることで、読みやすく安全なコードになります。
4. JOIN結果を受け取る構造体の例
ユーザーと注文を結合した結果を受け取る構造体の例です。
type UserOrder struct {
UserID int
UserName string
OrderID int
Price int
}
このように、SQLで取得する順番と同じ順番でフィールドを並べることが重要です。
5. JOINを使ったSQL文の例
次は、JOINを使ったSQL文の例です。
rows, err := db.Query(`
SELECT u.id, u.name, o.id, o.price
FROM users u
INNER JOIN orders o ON u.id = o.user_id
`)
INNER JOINは、両方のテーブルに一致するデータだけを取得します。
6. Scanで構造体にマッピングする
取得したデータは、Scanを使って構造体に入れます。
for rows.Next() {
var result UserOrder
rows.Scan(
&result.UserID,
&result.UserName,
&result.OrderID,
&result.Price,
)
}
Scanでは、SQLのSELECT順と構造体の順番が一致している必要があります。
7. 順番を間違えるとどうなるか
順番がズレると、意味の違う値が入ってしまいます。
これは、住所を書く欄に名前を書いてしまうようなものです。
エラーが出ない場合もあるため、特に注意が必要です。
8. NULLを含むJOIN結果の注意点
LEFT JOINなどを使うと、値が存在しない場合があります。
その場合は、sql.NullStringやsql.NullInt64などを使って受け取ります。
これにより、データがあるかどうかを安全に判断できます。
9. JOINと構造体マッピングの基本ルール
取得する列を明示的に書くことが大切です。
SELECT * を使わず、必要な列だけ指定しましょう。
構造体とSQLの対応関係を意識することで、複雑なクエリも怖くなくなります。