データ利活用が企業の競争力を左右する2026年において、SQL(Structured Query Language)はエンジニアだけでなく、データサイエンティストやマーケターにとっても必須のスキルとなりました。
膨大なデータから必要な情報を正確に抽出し、分析可能な形に整えるためには、SQLの各「句」を正しく理解し、適切に組み合わせる能力が求められます。
本記事では、SQLの基礎となる標準的な句から、近年のモダンなデータウェアハウス(BigQuery, Snowflake, PostgreSQL 16+など)で多用される高度な構文まで、実務に即した形で網羅的に紹介します。
各句の役割だけでなく、実行順序(論理的な処理フロー)やパフォーマンスへの影響についても深く掘り下げていきます。
SQLの基本構造と論理的な実行順序
SQLを記述する際、私たちは SELECT から書き始めますが、データベース内部での処理順序は異なります。
この「論理的な実行順序」を理解することは、複雑なクエリをデバッグしたり、実行速度を最適化したりする上で非常に重要です。
一般的なクエリの記述順序と、データベース内部での実行順序を比較してみましょう。
| 記述順序 | 句(Clause) | 論理的な実行順序 | 役割 |
|---|---|---|---|
| 1 | SELECT | 5 | 取得するカラムの指定、演算 |
| 2 | FROM | 1 | 対象とするテーブルの指定、結合(JOIN) |
| 3 | WHERE | 2 | 行の絞り込み(抽出条件) |
| 4 | GROUP BY | 3 | データのグループ化 |
| 5 | HAVING | 4 | グループ化後の絞り込み条件 |
| 6 | ORDER BY | 6 | 結果の並べ替え |
| 7 | LIMIT / OFFSET | 7 | 取得件数の制限 |
この表からわかるように、データベースはまず FROM 句でデータのソースを特定し、次に WHERE 句で不要なデータを除外します。
その後にグループ化や集計を行い、最後にようやく SELECT で指定されたカラムを抽出します。
この順序を意識することで、「なぜWHERE句でエイリアス(別名)が使えないのか」といった疑問を解消できるようになります。
基本的なデータ抽出で使用する句
まずは、あらゆるSQLの根幹を成す基本的な句について詳しく見ていきましょう。
SELECT句:取得カラムの指定
SELECT 句は、結果セットに含めるカラムを指定します。
すべてのカラムを取得する場合は \* (アスタリスク)を使用しますが、実務ではパフォーマンスと可読性の観点から、必要なカラムを明示的に指定することが推奨されます。
-- 基本的なSELECTの使用例
SELECT
user_id,
user_name,
email
FROM
users;
また、AS を使用してカラムにエイリアスを付与したり、計算式を含めたりすることも可能です。
SELECT
product_name,
price * 1.1 AS price_with_tax -- 消費税込みの価格を計算して別名を付与
FROM
products;
FROM句:データソースの指定
FROM 句は、データを取得するテーブルを指定します。
単一のテーブルだけでなく、後述する結合(JOIN)を用いて複数のテーブルを組み合わせる場合の起点となります。
WHERE句:行のフィルタリング
WHERE 句は、特定の条件に一致する行のみを抽出するために使用します。
数値の比較、文字列のパターンマッチング(LIKE)、範囲指定(BETWEEN)、リスト形式の指定(IN)など、多様な条件式を組み合わせて利用します。
SELECT
order_id,
order_date,
total_amount
FROM
orders
WHERE
status = 'completed' -- 完了した注文のみ
AND total_amount >= 5000 -- 5000円以上の注文
AND order_date >= '2026-01-01'; -- 2026年以降
WHERE句にインデックスが貼られたカラムを使用することは、クエリ高速化の基本中の基本です。
ORDER BY句:結果の並べ替え
ORDER BY 句は、取得した結果を指定したカラムの値に基づいてソートします。
昇順は ASC(省略可能)、降順は DESC を使用します。
SELECT
product_name,
stock_count
FROM
inventory
ORDER BY
stock_count DESC; -- 在庫が多い順に並べ替え
LIMIT句とOFFSET句:取得件数の制御
大量のデータを扱う際、上位数件だけを確認したい場合や、Webアプリケーションでのページネーション(ページ送り)を実現するために LIMIT と OFFSET を使用します。
SELECT
user_id,
last_login
FROM
users
ORDER BY
last_login DESC
LIMIT 10 OFFSET 20; -- 最新ログイン順に21件目から10件分を取得
データの集計とグループ化
ビジネス分析において、個々のデータを集計して「平均単価」や「月別売上」を算出する作業は不可欠です。
ここでは集計に関連する句を解説します。
GROUP BY句:データのグループ化
GROUP BY 句は、指定したカラムの値が同じ行を一つのグループにまとめます。
通常、SUM, AVG, COUNT, MAX, MIN などの集計関数と併用されます。
SELECT
category_id,
COUNT(*) AS product_count,
AVG(price) AS average_price
FROM
products
GROUP BY
category_id;
GROUP BY句を指定した場合、SELECT句には「グループ化に使用したカラム」か「集計関数」しか記述できないというルールがあるため注意が必要です。
HAVING句:グループ化後のフィルタリング
HAVING 句は、GROUP BY によってグループ化された後の結果に対してフィルタリングを行います。
WHERE 句が集計前の個々の行に対するフィルタリングであるのに対し、HAVING 句は集計値(SUMやCOUNTの結果など)に対する条件指定に用いられます。
SELECT
customer_id,
SUM(amount) AS total_spent
FROM
sales
GROUP BY
customer_id
HAVING
SUM(amount) > 100000; -- 合計購入金額が10万円以上の顧客のみ抽出
テーブルの結合(JOIN)
リレーショナルデータベースの真骨頂は、複数のテーブルを関連付けて情報を取得することにあります。
結合に関する句を整理しましょう。
INNER JOIN:内部結合
両方のテーブルに共通して存在するデータのみを取得します。
SELECT
o.order_id,
c.customer_name
FROM
orders AS o
INNER JOIN
customers AS c ON o.customer_id = c.customer_id;
LEFT OUTER JOIN / RIGHT OUTER JOIN:外部結合
一報のテーブルにあるすべての行と、もう一方のテーブルで一致する行を結合します。
一致するデータがない場合は NULL が入ります。
実務では、主となるテーブルを左側に書く LEFT JOIN が最も頻繁に利用されます。
SELECT
u.user_id,
p.profile_image_url
FROM
users AS u
LEFT JOIN
user_profiles AS p ON u.user_id = p.user_id;
-- プロフィール画像を設定していないユーザーも、画像URLをNULLとして取得できる
CROSS JOIN:交差結合(デカルト積)
2つのテーブルのすべての組み合わせ(全行 × 全行)を作成します。
マスタデータの全組み合わせ表を作る際などに重用されますが、データ量が膨大になるため注意が必要です。
集合演算子(SET操作)
複数の SELECT 文の結果を一つの結果セットに統合するための句です。
- UNION / UNION ALL:結果を縦に結合します。
UNIONは重複を除去し、UNION ALLは重複を含めたすべてを返します。パフォーマンス面ではUNION ALLの方が高速です。 - INTERSECT:両方のクエリ結果に含まれる共通の行を返します。
- EXCEPT (MINUS):1つ目のクエリ結果には含まれるが、2つ目の結果には含まれない行を返します。
モダンSQLにおける高度な句と構文
2026年現在のモダンなSQL開発において、クエリの可読性と保守性を高めるために必須となっている構文を紹介します。
WITH句:共通テーブル式 (CTE)
WITH 句(Common Table Expression)は、一時的な結果セットに名前を付けて定義し、その後のクエリでテーブルのように参照できる機能です。
ネストされた複雑なサブクエリを排除し、上から下へと論理的に流れるようなクエリを書くことができます。
WITH monthly_sales AS (
SELECT
DATE_TRUNC('month', order_date) AS sales_month,
SUM(amount) AS total_amount
FROM
orders
GROUP BY
1
)
SELECT
sales_month,
total_amount,
total_amount - LAG(total_amount) OVER (ORDER BY sales_month) AS diff_from_prev_month
FROM
monthly_sales;
OVER句:ウィンドウ関数
OVER 句は、行をグループ化せずに、現在の行に関連するデータセットに対して計算(移動平均、累計、ランキングなど)を行うウィンドウ関数を定義します。
PARTITION BYとORDER BY(ウィンドウ内)
ウィンドウ関数内でデータをどのように分割し、どの順序で並べるかを指定します。
SELECT
employee_name,
department_id,
salary,
RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS salary_rank
FROM
employees;
-- 部署ごとに給与が高い順にランキングを付与
CASE句:条件分岐
SQL内で if-then-else のようなロジックを実装します。
データのラベル付けや、特定の条件下での計算に非常に便利です。
SELECT
order_id,
CASE
WHEN amount >= 10000 THEN 'High Value'
WHEN amount >= 5000 THEN 'Medium Value'
ELSE 'Low Value'
END AS order_priority
FROM
orders;
QUALIFY句:ウィンドウ関数の結果をフィルタリング
一部のモダンなデータベース(Snowflake, BigQueryなど)で採用されている非常に強力な句です。
通常、ウィンドウ関数の結果(例:RANKの結果)で絞り込むにはサブクエリが必要ですが、QUALIFY を使えば WHERE のように直接フィルタリングが可能です。
SELECT
user_id,
event_time,
RANK() OVER (PARTITION BY user_id ORDER BY event_time DESC) AS event_rank
FROM
user_logs
QUALIFY
event_rank = 1; -- 各ユーザーの最新ログのみを1ステップで抽出
QUALIFY句は標準SQLではありませんが、対応している環境ではクエリを劇的に簡潔にします。
データ操作と定義に関する句
参照系だけでなく、データの更新や管理に用いる句も重要です。
INSERT / UPDATE / DELETE / MERGE
- INSERT INTO … VALUES / SELECT:データの新規挿入。
- UPDATE … SET:既存データの更新。
- DELETE FROM:行の削除。
- MERGE:通称「UPSERT」。対象データが存在すれば更新、存在しなければ挿入という処理を一括で行います。
CREATE / ALTER / DROP
- CREATE TABLE / VIEW / INDEX:オブジェクトの新規作成。
- ALTER TABLE:テーブル定義(カラム追加・型変更など)の変更。
- DROP:オブジェクトの削除。
TRUNCATE
テーブル内のすべての行を高速に削除します。
DELETE よりも高速ですが、ロールバックができないなどの制約があるため、慎重に使用する必要があります。
実務で役立つSQLの書き方とベストプラクティス
SQL句の一覧を覚えるだけでなく、それらをどう「美しく、速く」書くかがプロフェッショナルには求められます。
インデントとフォーマットの統一
SQL句はすべて大文字にする、カラム名の前にはカンマを置く(カンマプレフィックス)など、チーム内でのスタイルガイドを定めましょう。
-- 読みやすいフォーマットの例
SELECT
u.user_id
, u.display_name
, COUNT(o.order_id) AS total_orders
FROM users AS u
LEFT JOIN orders AS o
ON u.user_id = o.user_id
WHERE u.status = 'active'
GROUP BY 1, 2
ORDER BY 3 DESC;
SARGableなWHERE条件を書く
SARGable(Search ARGumentable)とは、インデックスを有効活用できる書き方のことです。
例えば、WHERE YEAR(order\_date) = 2026 と書くと、関数がカラムに適用されているためインデックスが使われません。
代わりに WHERE order\_date >= '2026-01-01' AND order\_date < '2027-01-01' と書くべきです。
ワイルドカード演算子の最適化
LIKE '%keyword%' のような前方一致でないパターンマッチングはフルスキャンを誘発します。
全文検索エンジンや転置インデックスを利用できない環境では、可能な限り前方一致 LIKE 'keyword%' を検討してください。
まとめ
本記事では、SQLの基本的な句から実務に不可欠なモダンな構文までを幅広く紹介しました。
SQLは誕生から数十年が経過した言語ですが、データ分析の現場では今なお最も重要な言語であり続けています。
特に WITH 句による構造化や、ウィンドウ関数の活用、そして QUALIFY のような最新の機能を使いこなすことで、複雑な要件もシンプルかつ高速なクエリで解決できるようになります。
まずは基本となる SELECT, FROM, WHERE, GROUP BY の論理的な処理順序を完璧にマスターしましょう。
その土台の上に、状況に応じた最適な句を選択できるスキルを積み上げていくことが、データエンジニアリングへの近道となります。
今回紹介した句を一つひとつ実際のデータセットで試し、その挙動を確認してみてください。
SQLの各句が持つ本来の力を引き出せるようになったとき、データから得られる洞察の質は劇的に向上するはずです。
