PROGスクールナビ

SQL中級・上級テクニック|JOIN・サブクエリ・ウィンドウ関数を解説

SQLはデータベースを操作する言語で、エンジニア・データアナリスト・マーケターまで幅広い職種で必要とされます。基礎の次に習得すべき中〜上級テクニックを解説します。

JOIN(テーブルの結合)

-- INNER JOIN(両テーブルに存在するデータのみ)
SELECT
  o.id AS 注文ID,
  u.name AS ユーザー名,
  o.amount AS 金額
FROM orders o
INNER JOIN users u ON o.user_id = u.id;

-- LEFT JOIN(左テーブルの全データ+右テーブルの一致データ)
SELECT
  u.name,
  COUNT(o.id) AS 注文数
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.name;

-- 複数テーブルの結合
SELECT
  o.id,
  u.name,
  p.product_name
FROM orders o
INNER JOIN users u ON o.user_id = u.id
INNER JOIN products p ON o.product_id = p.id;

サブクエリ(クエリの中にクエリ)

-- WHERE句のサブクエリ
SELECT name, salary
FROM employees
WHERE salary > (
  SELECT AVG(salary) FROM employees
);

-- FROM句のサブクエリ(インラインビュー)
SELECT dept, avg_salary
FROM (
  SELECT department AS dept, AVG(salary) AS avg_salary
  FROM employees
  GROUP BY department
) sub
WHERE avg_salary > 500000;

-- WITH句(CTE - 共通テーブル式):可読性が高い
WITH high_sales AS (
  SELECT user_id, SUM(amount) AS total
  FROM orders
  GROUP BY user_id
  HAVING SUM(amount) > 100000
)
SELECT u.name, h.total
FROM users u
INNER JOIN high_sales h ON u.id = h.user_id;

ウィンドウ関数(分析に強力)

-- ROW_NUMBER:行番号を振る
SELECT
  name,
  salary,
  ROW_NUMBER() OVER (ORDER BY salary DESC) AS rank
FROM employees;

-- RANK:同率順位あり
SELECT
  name,
  salary,
  RANK() OVER (ORDER BY salary DESC) AS rank
FROM employees;

-- LAG/LEAD:前後の行の値を取得
SELECT
  month,
  sales,
  LAG(sales) OVER (ORDER BY month) AS prev_month_sales,
  sales - LAG(sales) OVER (ORDER BY month) AS diff
FROM monthly_sales;

-- PARTITION BY:グループ内でのランキング
SELECT
  department,
  name,
  salary,
  RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS dept_rank
FROM employees;

パフォーマンス最適化

インデックスの活用

-- インデックス作成
CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_orders_created_at ON orders(created_at);

-- 複合インデックス(WHERE句の条件に合わせて作成)
CREATE INDEX idx_orders_user_date ON orders(user_id, created_at);

-- 実行計画の確認(MySQLの場合)
EXPLAIN SELECT * FROM orders WHERE user_id = 100;

クエリ最適化のポイント

  • SELECT *は避ける:必要な列だけ指定
  • WHERE句でインデックスを使う:関数でラップするとインデックスが効かない
  • N+1問題を避ける:ループの中でSQLを呼ばない

まとめ

SQL上級技術はJOIN→サブクエリ(CTE)→ウィンドウ関数の順で習得するのが最効率。データアナリスト・バックエンドエンジニアとしての市場価値が大幅に上がります。

📚 プログラミング初心者におすすめの本

🛒 楽天で人気のプログラミング入門書