はじめに
SQLで複雑な処理を記述する際、「サブクエリを使うべきか、WITH句(共通表式: Common Table Expression, CTE)を使うべきか」という疑問にあたったので調べてみました。
どちらも似たように“途中の結果を使い回す”仕組みですが、実際には読みやすさや最適化のされ方、再利用性などで違いがあります。
本記事ではそれぞれの特徴とメリット・デメリットを整理し、使い分けの指針を考えてみます。
サブクエリとは
サブクエリは、SELECT文の中にさらにSELECT文をネストする書き方です。条件式やFROM句の中で利用されることが多く、シンプルな集計や存在確認などに向いています。たとえば「平均給与より高い社員を取得する」クエリは以下のように書けます。
SELECT name, salary
FROM employees
WHERE salary > (
SELECT AVG(salary) FROM employees -- ここがサブクエリ
);
このようにサブクエリは直感的で短く書けるのが特徴です。
WITH句とは
WITH句は、SELECT文の冒頭に「一時的な名前付きテーブル」を定義できる構文です。定義した共通表式(CTE)は後続のクエリ内で参照できるため、処理を段階的に分割できます。先ほどと同じ例をCTEで書くと以下のようになります。
-- ここで共通表を定義
WITH avg_salary AS (
SELECT AVG(salary) AS value FROM employees
)
SELECT name, salary
FROM employees, avg_salary
WHERE employees.salary > avg_salary.value;
CTEを使うことで、クエリの構造がより「手続き的」に見えるようになります。
サブクエリのメリット・デメリット
メリット
- 短く書ける
単純な条件を一度だけ使う場合は、サブクエリの方がスッキリします。 - 初心者に分かりやすい
「条件の中で別の検索をする」という直感的なイメージに合います。 - 外部から見えない
サブクエリはローカルに閉じており、他の処理と干渉しにくい。
デメリット
- ネストが深くなりやすい
複雑な要件をサブクエリだけで書くと、入れ子が多くなり可読性が落ちます。 - 再利用できない
同じサブクエリを複数箇所で使う場合、毎回同じ記述を繰り返さなければなりません。 - 最適化がブラックボックス化する場合がある
DBエンジンによってはサブクエリがそのまま展開され、パフォーマンスが落ちることがあります。
WITH句のメリット・デメリット
メリット
- 可読性が高い
複雑な処理を分割して書けるため、クエリ全体の見通しが良くなります。 - 再利用できる
同じCTEを複数回参照できるため、冗長な記述を避けられます。 - 段階的な処理の表現に適している
途中結果に名前をつけられるので、「まず集計して、その結果をさらに絞り込む」といった手続きを自然に表現できます。 - 再帰クエリが書ける
WITH RECURSIVEを使えば階層構造の探索なども実現可能です。
デメリット
- 短い処理には冗長
単純な条件を一度だけ使うだけなら、わざわざCTEを定義するのは無駄に感じます。 - DBによってはパフォーマンスに差が出る
一部のDBMSではCTEが必ずマテリアライズされるため、無駄に中間結果を作ってしまうことがあります(ただしPostgreSQLやOracleなどでは最適化されるケースが多い)。 - 学習コスト
サブクエリに比べて構文がやや複雑に見えるため、初心者には抵抗感があるかもしれません。
使い分けの指針
シンプルな条件 → サブクエリ
平均値や存在確認など、短く書けるケースはサブクエリで十分です。
複雑なロジックや再利用が必要 → WITH句
複数段階の処理をわかりやすく整理したい場合はWITH句が有効です。
パフォーマンスが重要 → 実行計画を確認
DBエンジンによって最適化の挙動が異なるため、実際にEXPLAINで確認するのが安全です。
まとめ
サブクエリとWITH句はどちらも「途中の結果を使う」という点では同じですが、書き味や使いやすさには明確な違いがあります。
サブクエリはシンプルさ、WITH句は可読性と再利用性に強みがあります。
どちらが 「絶対に優れている」 ということはなく、ケースバイケースで選択するのが賢明です。特に大規模なSQLやチーム開発においては、可読性を重視してWITH句を活用する方が将来的な保守性に優れます。