質問サイトを巡回中に発見
LEFT JOIN
を実行した際に、NULL
の値を持つレコードが増えるケースについては認知していましたが、ただのJOIN
の時にもレコード数が増えることを経験しました。
SQLに詳しい方から見れば、当たり前でしょと思われるかもしれませんが、遭遇したのが初めて、例を見かけなかったので記事にしてみました。
前提条件
以下2つのテーブルがあります。subject
は別テーブルにしようかと思いましたが、今回は簡単のためexam_result
にVARCHAR(20)
として定義しています。
学生情報(student)
Table "public.student" Column | Type | Collation | Nullable | Default ------------+-----------------------+-----------+----------+--------- student_id | integer | | not null | name | character varying(50) | | not null | grade | integer | | not null | gendar | character(1) | | |
試験結果(exam_result)
Table "public.exam_result" Column | Type | Collation | Nullable | Default ----------------+-----------------------+-----------+----------+--------- exam_result_id | integer | | not null | student_id | integer | | not null | subject | character varying(20) | | not null | score | integer | | not null |
それぞれサンプルデータを用意しています。
postgres=# SELECT * FROM student; student_id | name | grade | gendar ------------+------------+-------+-------- 1 | 岡部倫太郎 | 2 | 1 2 | 椎名まゆり | 1 | 2 (2 rows)
postgres=# SELECT * FROM exam_result; exam_result_id | student_id | subject | score ----------------+------------+---------+------- 1 | 1 | 国語 | 34 2 | 1 | 数学 | 87 3 | 1 | 化学 | 75 4 | 2 | 国語 | 81 (4 rows)
結合してみると...
JOIN
を使って結合をした結果が以下です。元々、studentテーブルにはレコードが2件しかないのに結合結果には4件のレコード数が表示されています。
postgres=# SELECT * FROM student JOIN exam_result ON student.student_id = exam_result.student_id; student_id | name | grade | gendar | exam_result_id | student_id | subject | score ------------+------------+-------+--------+----------------+------------+---------+------- 1 | 岡部倫太郎 | 2 | 1 | 1 | 1 | 国語 | 34 1 | 岡部倫太郎 | 2 | 1 | 2 | 1 | 数学 | 87 1 | 岡部倫太郎 | 2 | 1 | 3 | 1 | 化学 | 75 2 | 椎名まゆり | 1 | 2 | 4 | 2 | 国語 | 81 (4 rows)
postgres=# SELECT COUNT(student_id) FROM student; count ------- 2
LEFT JOIN
の場合はどうでしょうか。こちらは想定通り結合後の4件が出力されました。
postgres=# SELECT * FROM student LEFT JOIN exam_result ON student.student_id = exam_result.student_id; student_id | name | grade | gendar | exam_result_id | student_id | subject | score ------------+------------+-------+--------+----------------+------------+---------+------- 1 | 岡部倫太郎 | 2 | 1 | 1 | 1 | 国語 | 34 1 | 岡部倫太郎 | 2 | 1 | 2 | 1 | 数学 | 87 1 | 岡部倫太郎 | 2 | 1 | 3 | 1 | 化学 | 75 2 | 椎名まゆり | 1 | 2 | 4 | 2 | 国語 | 81 (4 rows)
なぜ行数が増えるのか
理由は結合に用いているkeyが重複しているからです。今回の例で言うとstudent
への結合条件に指定しているstudent_id
がexam_result
テーブルで重複しています。これは岡部倫太郎が複数科目で試験を受けているためです。
student_id=1: 岡部倫太郎 student_id=1の試験結果: 国語, 数学, 化学
処理結果としては正常な動きですが、結合先に結合に用いたkeyの値が重複するようなケースは注意が必要になります。 というか、結合元のテーブルの行数が増えた!と捉えることが間違いで、結合によって新しく作られたテーブルには行数が4件ある条件が指定されていたと考える方が適切でしょう。