はじめに:データ分析の「共通言語」としてのSQL
データ分析の現場では、PythonやRといったプログラミング言語、あるいはTableauやPower BIといったBIツールが注目されがちです。しかし、それらのツールを使うにしても、その前段階として「データ」がなければ何も始まりません。そして、多くのビジネスデータはリレーショナルデータベース(RDB)に格納されており、そのデータを抽出・加工するための「共通言語」がSQL(Structured Query Language)です。
私自身、データ分析プロジェクトに携わる中で、SQLのスキルがデータ分析の効率と質を大きく左右することを痛感してきました。複雑なビジネス要件に応じたデータを正確かつ効率的に抽出・加工できるSQLスキルは、データサイエンティストやデータアナリストにとって必須の能力です。どんなに高度な機械学習モデルを構築できても、その元となるデータが適切に準備されていなければ、意味のある結果は得られません。
本記事では、データ分析に特化したSQLの実践的なテクニックを解説します。基本的な抽出・加工から、ウィンドウ関数やCTE(共通テーブル式)といった応用テクニックまで、具体的なビジネスケースを交えながら紹介します。あなたのデータ分析スキルを次のレベルへと引き上げるための一助となれば幸いです。
データ分析におけるSQLの重要性
- データの抽出: データベースから分析に必要なデータを取得する。
- データの加工: 取得したデータを分析しやすい形に整形する(集計、結合、変換など)。
- データの探索: データの傾向や異常値をSQLクエリで素早く確認する。
- ビジネスロジックの実装: SQLで直接ビジネスロジックを記述し、データウェアハウスなどで再利用可能なデータマートを作成する。
- データ品質の確認: データの欠損、重複、整合性などをSQLでチェックする。
基本的なデータ抽出・加工テクニック
1. データのフィルタリング (WHERE
句)
特定の条件を満たすレコードのみを抽出します。
-- 2024年1月以降の売上データで、購入金額が1000円以上のレコードを抽出
SELECT
order_id,
customer_id,
order_date,
amount
FROM
orders
WHERE
order_date >= '2024-01-01' AND amount >= 1000;
2. データの集計 (GROUP BY
, 集計関数)
特定のカテゴリごとにデータを集計します。COUNT
, SUM
, AVG
, MIN
, MAX
などの集計関数を使用します。
-- 地域ごとの総売上と平均購入金額を計算
SELECT
region,
SUM(amount) AS total_sales,
AVG(amount) AS average_purchase
FROM
orders
GROUP BY
region
HAVING
SUM(amount) > 100000; -- 総売上が10万円以上の地域のみ抽出
3. データの結合 (JOIN
)
複数のテーブルを結合して、関連する情報を取得します。
-- 顧客情報と注文情報を結合し、顧客名と注文金額を表示
SELECT
c.customer_name,
o.amount,
o.order_date
FROM
customers AS c
JOIN
orders AS o ON c.customer_id = o.customer_id
WHERE
o.order_date >= '2024-01-01';
4. データの変換 (CASE
式, 関数)
特定の条件に基づいてデータを変換したり、文字列操作や日付操作を行ったりします。
-- 購入金額に応じて顧客をセグメント分け
SELECT
customer_id,
amount,
CASE
WHEN amount >= 5000 THEN 'High Value'
WHEN amount >= 1000 THEN 'Medium Value'
ELSE 'Low Value'
END AS customer_segment
FROM
orders;
-- 日付から曜日を抽出 (PostgreSQLの例)
SELECT
order_date,
TO_CHAR(order_date, 'Day') AS day_of_week
FROM
orders;
応用データ抽出・加工テクニック
1. ウィンドウ関数 (Window Functions)
特定の「ウィンドウ」(行の集合)内で計算を行い、その結果を各行に返す関数です。ランキング、移動平均、累積和、前後の行との比較などに非常に強力です。
-- 顧客ごとの購入金額のランキングと、各注文の顧客内での累積購入金額
SELECT
customer_id,
order_date,
amount,
RANK() OVER (PARTITION BY customer_id ORDER BY amount DESC) AS rank_by_amount,
SUM(amount) OVER (PARTITION BY customer_id ORDER BY order_date) AS cumulative_amount
FROM
orders
ORDER BY
customer_id, order_date;
2. CTE (Common Table Expressions) / WITH
句
複雑なクエリを読みやすく、管理しやすくするために、一時的な名前付き結果セットを定義します。クエリの可読性を高め、再利用可能な中間結果を作成できます。
-- CTEを使って、まず月ごとの総売上を計算し、その結果から平均売上を計算
WITH monthly_sales AS (
SELECT
DATE_TRUNC('month', order_date) AS sales_month,
SUM(amount) AS total_monthly_sales
FROM
orders
GROUP BY
sales_month
)
SELECT
sales_month,
total_monthly_sales,
AVG(total_monthly_sales) OVER (ORDER BY sales_month ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS three_month_moving_avg
FROM
monthly_sales
ORDER BY
sales_month;
3. サブクエリ (Subqueries)
別のクエリの結果を、メインクエリの一部として使用します。SELECT
, FROM
, WHERE
, HAVING
句などで利用できます。
-- 平均購入金額以上の注文を抽出
SELECT
order_id,
customer_id,
amount
FROM
orders
WHERE
amount > (SELECT AVG(amount) FROM orders);
4. ピボット/アンピボット (Pivot/Unpivot)
行と列を入れ替えることで、データの見方を変え、分析しやすい形に整形します。データベースシステムによって構文が異なりますが、CASE
式と集計関数を組み合わせることで実現できます。
-- 月ごとの製品カテゴリ別売上を横持ちに変換 (PostgreSQLの例)
SELECT
DATE_TRUNC('month', order_date) AS sales_month,
SUM(CASE WHEN product_category = 'Electronics' THEN amount ELSE 0 END) AS electronics_sales,
SUM(CASE WHEN product_category = 'Books' THEN amount ELSE 0 END) AS books_sales,
SUM(CASE WHEN product_category = 'Clothing' THEN amount ELSE 0 END) AS clothing_sales
FROM
orders
GROUP BY
sales_month
ORDER BY
sales_month;
SQLを使ったビジネス分析の例
顧客のRFM分析
RFM分析は、顧客の行動(Recency: 最新購入日、Frequency: 購入頻度、Monetary: 購入金額)に基づいて顧客をセグメンテーションする手法です。SQLでこれらの指標を計算できます。
-- RFM指標の計算
SELECT
customer_id,
MAX(order_date) AS last_purchase_date, -- Recency
COUNT(DISTINCT order_id) AS purchase_frequency, -- Frequency
SUM(amount) AS total_monetary -- Monetary
FROM
orders
GROUP BY
customer_id;
コホート分析
特定の期間にサービスを開始したユーザーグループ(コホート)の行動を追跡し、時間の経過による変化を分析します。ユーザーの定着率やLTV(顧客生涯価値)の分析に役立ちます。
-- ユーザーの初回購入月を特定し、月ごとの定着率を計算する準備
WITH first_purchase AS (
SELECT
customer_id,
MIN(order_date) AS cohort_month
FROM
orders
GROUP BY
customer_id
)
SELECT
fp.cohort_month,
DATE_TRUNC('month', o.order_date) AS purchase_month,
COUNT(DISTINCT fp.customer_id) AS cohort_size,
COUNT(DISTINCT o.customer_id) AS active_customers
FROM
first_purchase AS fp
JOIN
orders AS o ON fp.customer_id = o.customer_id
WHERE
DATE_TRUNC('month', o.order_date) >= fp.cohort_month
GROUP BY
fp.cohort_month, purchase_month
ORDER BY
fp.cohort_month, purchase_month;
実体験に基づくSQL実践の教訓
1. まずは「何が知りたいか」を明確にする
SQLを書く前に、必ず「このデータから何を知りたいのか」「どのようなビジネス課題を解決したいのか」を明確にしましょう。目的が曖昧だと、無駄なクエリを書いてしまったり、分析結果がビジネスに繋がらなかったりします。
2. 実行計画を確認する
複雑なクエリや大規模なデータに対しては、EXPLAIN
(PostgreSQL, MySQLなど)やEXPLAIN PLAN
(Oracle)を使ってクエリの実行計画を確認しましょう。これにより、どの部分がボトルネックになっているのかを特定し、クエリを最適化できます。
3. データの特性を理解する
データベースのスキーマ、データ型、インデックス、データの分布などを理解することは、効率的なSQLを書く上で不可欠です。特に、NULL値の扱いや、文字列比較の際のパフォーマンスなどを意識しましょう。
4. 可読性を意識する
複雑なクエリほど、可読性が重要になります。適切なインデント、コメント、CTEの活用、サブクエリの適切な利用などを心がけましょう。他の人が読んでも理解しやすいクエリは、保守性も高まります。
5. テストと検証を怠らない
書いたSQLクエリが正しい結果を返すか、必ずテストと検証を行いましょう。特に、データの結合や集計を行う際は、想定通りの結果になっているか、エッジケースは考慮されているかなどを注意深く確認する必要があります。
まとめ:SQLでデータ分析の可能性を広げる
SQLは、データ分析者にとって最も基本的でありながら、非常に強力なツールです。基本的な抽出・加工テクニックから、ウィンドウ関数やCTEといった応用テクニックまでを習得することで、ビジネス要件に応じた複雑なデータ操作を効率的に行えるようになります。
本記事で解説したSQLの実践テクニックと、私の実体験に基づいた教訓は、あなたがデータ分析を通じてビジネスに真の価値をもたらすための一助となるでしょう。特に、ビジネス課題の明確化、実行計画の確認、そして可読性を意識したクエリ作成は、SQLスキルを向上させる上で不可欠です。
データドリブンな意思決定が求められる現代において、SQLを使いこなせる能力は、データ分析者として市場価値を高める上で非常に重要です。ぜひ、あなたのプロジェクトでも本記事の内容を参考に、SQLの力を活用してビジネスの成長をドライブしてください。
参考文献:
* SQLとは
* ウィンドウ関数
* 共通テーブル式 (CTE)
* RFM分析
* コホート分析
コメント