キーワード

SQLの「join vs サブクエリ」どちらを選ぶ?シーン別対決!–おつまみとしてのソースコード第10皿

ユニークで面白い、意外なアイディアが詰め込まれているソースコードの世界をおつまみ感覚で紹介するのが、情シスのじかんの「おつまみとしてのソースコード」です!週末も近づき、ちょっと一息つきたくなる木曜日の夕方にお届けしていきます。

情シスのみなさんが、日常的に触れる機会も多いであろうSQL。データを抽出する際に、「あれ、この処理ってJOINで書くべき?それともサブクエリの方がいいのかな?」と、ふと手が止まる瞬間はありませんか?
JOINとサブクエリ、どちらを使っても望んだ結果が得られることも多いですよね。でも、「パフォーマンスや可読性を考慮すると、どちらの方が適した書き方なのか?」という疑問が頭をかすめる時もあると思います。

そんな小さなモヤモヤを解消すべく、今宵はSQL界の二大巨頭、「JOIN」選手と「サブクエリ」選手をお招きし、SQLの「よくあるシーン」で直接対決させてみます!

おつまみとしてのソースコードの第十回は「join vs サブクエリ」。この記事を読めば、明日からのSQLコーディングで、少し自信を持って書き方を選べるようになることでしょう。
エンジニア仲間とのアイスブレイクや、一人でまったりする時間のお供に、ぜひご覧ください!

         

リングイン!「JOIN」「サブクエリ」両選手のご紹介

では、さっそく両選手の入場です!まずはそれぞれの選手の持つ技と特徴を簡単にご紹介していきます。

【赤コーナー】JOIN選手!

■得意技

テーブル連結。INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL OUTER JOINなど多彩な技を持つ。

■特徴

複数のテーブルを関連キーでガッチリ結合!関連する情報をまとめて複数のテーブルから引き出す力持ちです。リレーショナルデータベースの真骨頂、テーブル間の「関係性」を利用してデータを操作するのが大得意です!

【青コーナー】サブクエリ選手!

得意技

入れ子構造。SELECT句、FROM句、WHERE句、HAVING句など、SQL文のあらゆる場所に潜り込み、華麗にデータ操作を実現します!

特徴

SQL文の中に、もう一つのSQL文を忍ばせるトリッキーな技を使います。マトリョーシカ人形のように、処理を段階的に実行したり、複雑な条件を指定したりするのが得意です。

JOIN選手とサブクエリ選手、どちらもSQLを書く上で欠かせない、頼れる存在です。それでは、いよいよ対決のゴングを鳴らしましょう!

いざゴング!シーン別対決 4番勝負!

それでは、いよいよ対決開始です!4つのよくあるシチュエーションで、どちらの書き方がよりよいのか判定していきましょう!

【第1ラウンド】単純なデータ連結|社員名と部署名が欲しい!

お題
社員テーブル(Employees)と部署テーブル(Departments)を結合して、社員名とその所属部署名の一覧を取得する。基本中の基本ですね!

 

いざ対決!それぞれの戦い方

では、両選手の戦い方を見ていきましょう。

【JOIN選手】

SELECT
e.employee_name,
d.department_name
FROM
Employees e
INNER JOIN
Departments d ON e.department_id = d.department_id;

【サブクエリ選手】

SELECT
e.employee_name,
(SELECT d.department_name FROM Departments d WHERE d.department_id = e.department_id) AS department_name
FROM
Employees e;

・判定

JOIN選手の勝利!

このような単純なテーブル結合の場合、一般的にJOINの方がシンプルで、「テーブルを結びつけている」という意図がSQLから明確に伝わります。また、多くのデータベースシステムでは、JOINの方が、SQL実行の司令塔であるオプティマイザが処理計画を立てやすく、パフォーマンスが良い傾向があります。
サブクエリの中でも、特にSELECT句などで利用されるスカラ・サブクエリは、行ごとに処理が実行されるイメージのため、データ量が多い場合に遅くなる可能性があります。

【第2ラウンド】集約結果との比較|平均給与よりリッチな社員は誰だ!?

お題
社員情報・給与情報を含む社員テーブル(Employees)から全社員の平均給与を計算し、その平均給与よりも高い給与をもらっている社員の情報を取得したい。集計結果を使うパターンです。

 

いざ対決!それぞれの戦い方

【JOIN選手】

SELECT
e.*
FROM
Employees e
JOIN
(SELECT AVG(salary) AS avg_salary FROM Employees) avg_table
ON e.salary > avg_table.avg_salary;

【サブクエリ選手】

SELECT
*
FROM
Employees
WHERE
salary > (SELECT AVG(salary) FROM Employees);

・判定

サブクエリ選手の勝利!

このケースでは、WHERE句にサブクエリを書く方が「給与が平均給与よりも大きい」という条件を非常にストレートに表現できており、可読性が高いと言えます。
JOINを使った書き方も間違いではありませんが、平均給与を計算するためだけの一時的なテーブル(avg_table)を作る必要があり、少し回りくどい印象を受けるかもしれません。

【第3ラウンド】存在チェック|特定の注文履歴がある顧客を探せ!

お題
顧客テーブル(Customers)と注文履歴テーブル(Orders)があり、特定の商品(商品IDが’A001’の商品)を購入したことがある顧客のリストを取得したい。「〜したことがあるかどうか」を知りたい場面です。

 

いざ対決!それぞれの戦い方

【JOIN選手】

SELECT DISTINCT
c.customer_id,
c.customer_name
FROM
Customers c
INNER JOIN
Orders o ON c.customer_id = o.customer_id
WHERE
o.product_id = ‘A001’;

【サブクエリ選手】

SELECT
c.customer_id,
c.customer_name
FROM
Customers c
WHERE
EXISTS (
SELECT 1
FROM Orders o
WHERE o.customer_id = c.customer_id
AND o.product_id = ‘A001’
);

・判定

サブクエリ選手の勝利!

EXISTSは、サブクエリ内の条件に一致する行が 1件でも見つかった時点 でTRUEを返し、その後の検索を打ち切るため、非常に効率的に動作することが多いです。
一方、JOINでは条件に合うすべての行を結合するうえに、このケースでは重複排除(DISTINCT)のコストもかかる場合があります。パフォーマンス面でEXISTSに軍配が上がるという判定が妥当であるといえるでしょう。

【第4ラウンド】自己結合|自分自身との関係を探る!

お題
社員テーブル(Employees)には、各社員の情報に加え、その社員の上司にあたる人の社員番号(manager_id)が格納されています。全社員について、「社員名」とその「直属の上司の名前」を一覧で表示したい、という状況です。社長などの上司がいない社員は上司名をNULLで表示します。

 

いざ対決!それぞれの戦い方

【JOIN選手】

SELECT
e.employee_name,
m.employee_name
FROM
Employees e
LEFT JOIN
Employees m ON e.manager_id = m.employee_id;

【サブクエリ選手】

SELECT
e.employee_name,
(
SELECT m.employee_name
FROM Employees m
WHERE m.employee_id = e.manager_id
)
FROM
Employees e;

・判定

JOIN選手の勝利!

このように「同じテーブル内にあるレコード同士の関係性」(親子関係、階層関係など)を扱いたい場合、自己結合が最も標準的で、意図が明確になります。サブクエリでも同じ結果は得られますが、各社員レコードに対して上司の名前を個別に検索するような形になり、多くの場合JOINよりもパフォーマンスが劣る可能性があります。

結局どう使い分ける?「JOIN OR サブクエリ」考え方のステップ

勝負の結果をご覧いただいた通り、JOINとサブクエリは「常にJOINが良い」「常にサブクエリが良い」という単純な話ではないことがお分かりいただけたかと思います。
では、日々の業務でどちらを使うか迷ったとき、結局のところどのように考えていけばよいのでしょうか?迷った時の考え方を説明していきます。

1.まず書いてみる

まずは、自分が「書きやすい」「直感的によい」と感じる方で、動くSQLを書いてみましょう。

2.パフォーマンスを意識する

もし処理対象のデータ量が多かったり、レスポンス速度が求められたりするなら、実行計画を確認しましょう。ボトルネックになっている箇所を特定し、必要であればJOINとサブクエリの書き換えを検討します。

3.可読性を確認する

少し時間を置き、あらためてSQLを読んだ時に、そのSQLが何をしようとしているのかを直観的に理解できるかを確認しましょう。分かりにくい場合は、WITH句を使うなど、リファクタリングを検討します。

まとめ

「JOIN vs サブクエリ」対決、楽しんでいただけましたでしょうか?

JOINもサブクエリも、それぞれに得意な土俵があり、どちらもSQLコーディングには欠かせないテクニックです。それぞれの特徴、メリット・デメリットを理解し、目の前にある課題や状況に応じて使い分けることが、よりよいSQLを書くための鍵となります。

パフォーマンスと可読性、時にはその両立に頭を悩ませることもあるかと思いますが、それもSQLの面白さでもあります。本記事の内容を参考にすることで、皆さんのSQLライフがより快適になることを願っています!

著者:羽守ゆき
大学を卒業後、大手IT企業に就職。システム開発、営業を経て、企業のデータ活用を支援するITコンサルタントとして10年超のキャリアを積む。官公庁、金融、メディア、メーカー、小売など携わったプロジェクトは多岐にわたる。現在もITコンサルタントに従事するかたわら、ライターとして活動中。
 
 

特集|仕事で疲れた脳みそをリフレッシュ♬
おつまみとしてのソースコード

木曜日の夕方に仕事で疲れた脳みそをリフレッシュしたいとき、一人でゆっくりしたい夜、ちょっとした空き時間に、気軽に「つまめる」ソースコードの話題をお届けします。

まるで隠れ家バーでマスターが語るウンチクのように、普段は見過ごしがちなコードの奥深さや、思わず「へぇ〜!」と唸るようなユニークなアイデア、クスッと笑える小ネタを、ソースコードの世界を熟知した「情シスのじかん」がご紹介します。

コードを書くのが大好きなエンジニアさんも、ソースコードはちょっと苦手…という情シス部門の方も、この特集を読めば、きっとソースコードの新たな一面を発見できるはず。

業務効率化のヒントになるTipsや、セキュリティ対策に役立つ情報も盛りだくさん。

さあ、あなたも「おつまみとしてのソースコード」で、技術の世界をもっと身近に、もっと楽しく感じてみませんか?

本特集はこちら
 

関連記事Related article

       

情シスのじかん公式InstagramInstagram

       

情シスのじかん公式Instagram

30秒で理解!フォローして『1日1記事』インプットしよう!

close close