88
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

若手が教えるSQLの書き方・豆知識10選

Last updated at Posted at 2025-12-13

※本記事はOracleユーザー向けに書いてあります。

SQLに慣れてきた?社会人3年目。
SELECT・JOIN・GROUP BYはもう普通に書ける。
でも、「なんか遅い」「意図通りの結果が出ない」と感じることが増えてくると思います

この記事では、3年目以降のSQL使いが知っておくと仕事が速く・正確になる豆知識10選を紹介します。

① INNER JOIN と LEFT JOIN の本当の違い

INNER JOIN は「両方に存在する行」を返す。
LEFT JOIN は「左テーブルの行をすべて残す」。

SELECT *
FROM EMP e
LEFT JOIN DEPT d ON e.DEPT_ID = d.DEPT_ID
WHERE d.DEPT_NAME = '営業';

この書き方、実は LEFT JOIN の意味が消えます。
WHEREで右テーブル条件を書くとINNER JOIN扱いになるためです。

✅ 正しい書き方:

SELECT *
FROM EMP e
LEFT JOIN DEPT d 
  ON e.DEPT_ID = d.DEPT_ID 
  AND d.DEPT_NAME = '営業';

② サブクエリより WITH句(共通テーブル式)を使う

ネストが深くなるSQLはメンテが辛いので避けましょう。
WITH句を使えば、部分ごとに名前を付けて分けられます。

WITH SALES_2025 AS (
  SELECT * FROM SALES WHERE YEAR = 2025
)
SELECT COUNT(*) 
FROM SALES_2025
WHERE AMOUNT > 100000;

● ポイント:
WITH句は「仮想テーブル」。
読みやすさ・再利用性・レビューしやすさが一気に向上します。

③ IN と EXISTS の使い分け(パフォーマンス差)

条件 向いてる構文
サブクエリが小さい IN
サブクエリが大きい EXISTS

IN:小さいテーブル向け

SELECT * FROM EMP 
WHERE DEPT_ID IN (SELECT DEPT_ID FROM DEPT);

EXISTS:大きいテーブル向け

SELECT * FROM EMP e 
WHERE EXISTS (SELECT 1 FROM DEPT d WHERE e.DEPT_ID = d.DEPT_ID);

豆知識:
EXISTS は条件成立時に即終了するため、大規模データに強いです。

④ 集計関数はNULLを除外する

SELECT AVG(SCORE) FROM TEST;

NULLは自動的に除外されるため、平均が高く出ることがあります。

✅ 対策:

SELECT AVG(COALESCE(SCORE, 0)) FROM TEST;

豆知識:
COALESCE はNULLを安全に置き換える関数。
OracleやPostgreSQLでも共通で使えるSQL標準構文です。

⑤ 結果の順序保証には ORDER BY が必須

SQLはデフォルトでは順序を保証しません。
ORDER BYがなければ、DBの内部処理順に依存します。

SELECT * FROM EMP;               -- 順序保証なし
SELECT * FROM EMP ORDER BY EMP_ID; -- 順序保証あり

⑥ パフォーマンス改善の三原則

SELECT *は禁止(必要な列だけ取る)

WHEREで列に関数を使わない(インデックスが効かない)

ORよりIN、INよりJOINを検討する

悪い例

WHERE TO_CHAR(REG_DATE, 'YYYYMM') = '202511'

良い例

WHERE REG_DATE >= DATE '2025-11-01'
  AND REG_DATE <  DATE '2025-12-01'

● ポイント:
関数をWHEREで使うと、全件スキャンになります。
インデックスを活かす書き方を意識しましょう。

⑦ ダミー値の扱いで集計崩れを防ぐ

NULLは集計で無視されるため、明示的に置き換える。

SELECT COALESCE(SCORE, 0) AS SCORE FROM TEST;
SELECT COALESCE(NAME, '(未登録)') AS NAME FROM USER;

豆知識:
OracleのNVLよりも、SQL標準のCOALESCEを使うと他DBでも動きます。

⑧ ウィンドウ関数(分析関数)を覚える

グループごとの順位・累積などを求めたいときに強力。

SELECT 
  DEPT_ID,
  EMP_NAME,
  RANK() OVER(PARTITION BY DEPT_ID ORDER BY SALARY DESC) AS RANK_IN_DEPT
FROM EMP;

● ポイント:
GROUP BYでは潰れてしまうデータも、
ウィンドウ関数なら「グループ単位の行ごと分析」ができます。

⑨ COUNT の最適化を意識する

大規模テーブルで COUNT(*) は重くなりがち。

✅ 対策:

インデックス列をCOUNT対象にする

Oracleなら統計情報(NUM_ROWS)を活用

実行計画(EXPLAIN)で全件走査になっていないか確認

▲ 豆知識:
COUNTは“重い関数”の代表格。
必要なときだけ実行する設計にすると格段に速くなります。

⑩ 集計テーブルを作るという選択肢

同じJOIN・GROUP BYを何度も使うようなら、
**中間集計テーブル(マート)**を作るのが正解です。

CREATE MATERIALIZED VIEW SALES_SUMMARY AS
SELECT DEPT_ID, SUM(AMOUNT) AS TOTAL
FROM SALES
GROUP BY DEPT_ID;

● ポイント:
SQLをチューニングするより、「SQLを書かない構造」を作る。

■ まとめ

観点 初級者 中級者
クエリの目的 とにかく動かす 結果の意味を考える
JOINの理解 なんとなく結合 条件の順序まで意識
集計の考え方 関数を使う NULL・順序・性能を考慮
設計の視点 クエリ単体最適化 テーブル設計から最適化

・最後に

SQLは「書ける」から「読める」「設計できる」へ。
3年目のいまこそ、結果の“理由”を理解するSQL力を磨く時期です。

気づけば「SQL詳しい人」として一目置かれるようになります。
今日から少しずつ、“動くSQL”から“意図を持つSQL”へ進化しましょう。

88
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
88
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?