
SQLもPythonも勉強したのに、なぜか実務評価が伸びない…
コードは書けるのに「意思決定にどう繋げるの?」と言われがち…
本記事の結論はシンプルです。評価されるのは、SQLだけでもPythonだけでもなく、両者を正しい順番で“接着”し、意思決定に翻訳できる人。鍵は、(1) 粒度・主キー・時点の設計、(2) SQLで正しいテーブルを作る、(3) Pythonで検証・可視化・自動化、(4) PDFとRunbookで運用の4ステップです。
この記事で身につくこと
- 粒度・主キー・時点を軸にしたデータ設計の型
- 現場で通るSQL 12パターン(期間JOIN/ウィンドウ/重複排除ほか)
- SQL→pandasハンドオフの再現性確保テク
- pytest×可視化で品質担保→意思決定に翻訳する流れ
- PDF化・スケジューリングまでの運用テンプレ
関連記事:
>>データサイエンティストの仕事内容と必要スキル【年収レンジ付き】“意思決定を速く・正しくする”職種の全体像
>>はじめてのSQL:SELECT/WHERE/GROUP BYを最短で理解【コピペOK】
>>【保存版】pandas基礎:データフレームの作成・整形・結合・集計を“実務の型”で身につける
>>【保存版】scikit-learn基礎:回帰・分類・前処理・パイプライン・交差検証を“実務の型”で習得
>>コピペで回るレポート納品|Jupyter→PDF/HTML→共有の自動化テンプレ
>>自動化:スケジューリングと業務改善の型|「再実行安全×観測可能×静かに動く」を仕組みにする
>>Docker超入門:学習環境を箱ごと保存する|“同じ環境が誰でも動く”を最小コストで実現
>>【コピペOK】pytestで“壊れないPython”を作る12ステップ
評価されない理由は「順番ミス」──まず設計、次にSQL、最後にPython
よくあるつまずきは次の4つに集約されます。粒度崩壊(日次と注文行が混在)、時点誤り(価格や会員属性の有効期間を無視)、ハンドオフ迷子(型やタイムゾーンの不一致)、そして運用不在(Notebookで止まる)。
解決は順番です。先にテーブル設計、次にSQLで正しく作る、最後にPythonで検証→運用。
現場エピソード
筆者(ふみと)は大手企業で10年、100件以上の案件を担当しました。評価されたのは、「SQLで正しく出す → Pythonで検証 → 意思決定に翻訳」の速さと安定。粒度・主キー・時点を1枚のデータ辞書に落とし、SQLのCTEで“意味のある表”を積み上げ、pandasで再現性の検査を回す──この型で炎上案件が驚くほど減りました。
ステップ1:粒度・主キー・時点を決める(データ辞書テンプレ)
まずは行が何を表すのか(粒度)、一意な組(主キー)、どの時点の値かを明確にします。ここが曖昧だと、以降のSQL・可視化・モデル化まで全部がブレます。
テーブル: orders
粒度: 注文行(order_id, line_no)
主キー: (order_id, line_no)
時刻: ordered_at(JST)
外部参照: customers(customer_id), price_history(sku, valid_from, valid_to)
ステップ2:現場で通るSQL 12パターン(コピペOK)
以下はANSI SQL+CTEベースの“通る”書き方。各スニペットに粒度のコメントを付け、二重計上やN×Nの暴発を防ぎます。
P1|日次整形(注文行→日次)
WITH daily AS (
SELECT DATE(ordered_at) AS d, SUM(amount) AS sales
FROM order_lines
GROUP BY DATE(ordered_at)
)
SELECT d, sales FROM daily ORDER BY d;
-- 粒度: 日
P2|ウィンドウ関数(RFM/累計/移動平均)
SELECT customer_id,
MAX(ordered_at) OVER w AS last_order_at,
COUNT(*) OVER w AS freq,
SUM(amount) OVER w AS monetary
FROM orders
WINDOW w AS (PARTITION BY customer_id);
-- 粒度: 注文行(集計は窓で顧客粒度に投影)
P3|期間JOIN(価格や会員ランクの有効期間)
SELECT o.order_id, o.sku, p.price
FROM orders o
JOIN price_history p
ON o.sku = p.sku
AND o.ordered_at >= p.valid_from
AND (p.valid_to IS NULL OR o.ordered_at < p.valid_to);
-- 粒度: 注文行(“時点一致”での参照)
P4|SCD2風スナップショット(会員属性の履歴)
SELECT c.customer_id, a.attr, a.valid_from, a.valid_to
FROM customers c
JOIN customer_attr a
ON c.customer_id = a.customer_id;
-- 下流JOINはP3のBetween条件で
P5|アンチJOIN(解約済み除外・除外リスト)
SELECT * FROM customers c
LEFT JOIN churned_list x ON c.customer_id = x.customer_id
WHERE x.customer_id IS NULL;
P6|重複排除(最新レコードのみ)
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER(
PARTITION BY order_id ORDER BY updated_at DESC) AS rn
FROM orders_staging
) t WHERE rn = 1;
P7|キー整合チェック(多対多の暴発検知)
SELECT sku, COUNT(DISTINCT price) AS n
FROM price_history GROUP BY sku HAVING n > 1;
-- “同時点に2価格”の異常などを別途検査
P8|セッション化(Webログ)
SELECT user_id, session_id,
MIN(ts) AS start_ts, MAX(ts) AS end_ts
FROM (
SELECT *, SUM(new_session) OVER (
PARTITION BY user_id ORDER BY ts) AS session_id
FROM (
SELECT *, CASE WHEN LAG(ts) OVER(PARTITION BY user_id ORDER BY ts)
< ts - INTERVAL '30 MINUTE' THEN 1 ELSE 0 END AS new_session
FROM pageviews
) x
) y
GROUP BY user_id, session_id;
P9|“日割り”在庫の生成(スナップショット展開)
WITH spans AS (
SELECT sku, valid_from, COALESCE(valid_to, CURRENT_DATE) AS valid_to, stock
FROM stock_span
), days AS (
SELECT sku, DATE(d) AS d, stock
FROM spans, LATERAL (SELECT generate_series(valid_from, valid_to, INTERVAL '1 day') AS d) g
)
SELECT * FROM days;
-- 粒度: sku-日(倉庫の可用性を日次へ)
P10|N対Nの安全な集計(ダブルカウント回避)
WITH base AS (
SELECT DISTINCT o.order_id, l.sku
FROM orders o JOIN order_lines l USING(order_id)
)
SELECT sku, COUNT(*) AS orders FROM base GROUP BY sku;
-- DISTINCTで粒度を“注文-商品”に正規化して計数
P11|A/Bテストの事前バランス
SELECT "group", AVG(age) AS avg_age, AVG(spend) AS avg_spend
FROM ab_users GROUP BY "group";
-- Python側でCI/検定へ
P12|実行計画を味方に(インデックス候補)
絞り込み列(WHERE
/JOIN
)は複合Index、時系列は(customer_id, ts)
。EXPLAIN
でフルスキャンが出たら設計を見直しましょう。
ステップ3:SQL→pandasの“壊れにくい”受け渡し
型・タイムゾーン・主キーの一意性を明示するだけで、再現性はグッと上がります。
import sqlite3, pandas as pd
con = sqlite3.connect("app.db")
q = open("sql/feature_store.sql").read()
dtypes = {"customer_id": "Int64", "sku": "string"}
df = pd.read_sql_query(q, con, parse_dates=["ordered_at"], dtype=dtypes)
# 粒度の確認(主キーの一意性)
assert df.groupby(["order_id","line_no"]).size().le(1).all()
# タイムゾーン(DBはUTC想定)
# df\["ordered\_at"] = (df\["ordered\_at"]
# .dt.tz\_localize("UTC").dt.tz\_convert("Asia/Tokyo"))
カテゴリ列はastype('category')
でメモリ削減と意図の明示、巨大テーブルはchunksize
で逐次処理に。
ステップ4:品質チェック&可視化で“説明可能”に
pytestで壊れにくさを担保
# tests/test_feature_store.py
import pandas as pd
def test\_primary\_key\_unique(feature\_store: pd.DataFrame):
assert not feature\_store.duplicated(\["order\_id","line\_no"]).any()
def test\_value\_ranges(feature\_store):
assert feature\_store\["amount"].ge(0).all()
# 期間JOINの欠損比率なども検査推奨
可視化・検証の要点
まずは3枚:推移(売上/件数)・寄与(カテゴリ別)・関係(価格×数量)。モデルを使うなら、ベースライン→CV→学習曲線→重要度の順で、ストーリーラインに沿って説明します。
[内部リンク:可視化入門] / [内部リンク:scikit-learn基礎] / [内部リンク:モデル評価]
運用:Notebook→PDF化→スケジューリング
papermill → nbconvert
で週次PDFを自動出力し、APScheduler/cronで毎週月曜8:30に回す。Runbookには失敗時の抑止/再実行/連絡先を1ページで。
[内部リンク:データレポート納品テンプレ:Jupyter→PDF→共有まで] / [内部リンク:自動化:スケジューリングと業務改善の型] / [内部リンク:Docker超入門]
“通る”提出物テンプレ(SQL+Python+PDF)
project-sql-python/
sql/feature_store.sql
notebooks/10_eda.ipynb
src/report.py
tests/test_feature_store.py
requirements.txt
Dockerfile
README.md # 再現手順1画面
dist/report_YYYYMMDD.pdf
再現手順:
1) docker build -t report .
2) docker run -v $(pwd):/work report python -m src.report
データ: /data/orders.csv, price_history.csv
出力: dist/report_YYYYMMDD.pdf
用途別の第一手(すぐ動く)
転職(3ヶ月内):本記事の12パターンSQLから3つ(期間JOIN/ウィンドウ/重複排除)で提出物を作る。[内部リンク:未経験からデータサイエンティストへ:6ヶ月ロードマップ] / [内部リンク:ポートフォリオ完全ガイド]
副業(社内自動化):日次整形→PDFのラインを確立し、効果額を円で説明。[内部リンク:Python副業の始め方:月3〜10万円を目指す現実的ステップ]
在宅×子育て:朝活1hでSQL1本→図1枚を習慣化。[内部リンク:在宅×Python:子育てと両立する1日1時間学習術]
よくある面接/実技お題→対策
- 売上TopNと寄与率:
SUM(amount)
、RANK() OVER
、累積寄与。 - 最新状態の抽出:
ROW_NUMBER() OVER (PARTITION BY ... ORDER BY updated_at DESC) = 1
。 - 価格の有効期間適用:P3のBetween JOIN。
- A/Bの母数・率:
COUNT(*) / NULLIF(COUNT(*),0)
、PythonでCI。 - ダブルカウント回避:P10の正規化→計数。
まとめ:SQL×Pythonは“接着”で差がつく
評価を分けるのは、スキルの“足し算”ではなく接着のうまさ。粒度・主キー・時点を定義→SQLで正しく出す→Pythonで検証・可視化→PDF化して定期運用。この流れを1本通せば、実務でも面接でも「誰でも回せる」提出物で説得力が増します。
伴走します:SQL設計→検証→運用まで同伴
無料カウンセリング/体験を活用し、SQLレビュー→Python検証→PDF運用まで“挫折しない接着”を一緒に作ります。
TechAcademy データサイエンスコース(受講料:174,600円~ ※更に割引あり)

株式会社キカガク AI人材長期育成コース(受講料:237,600円~)

この記事から次に読むべきもの(内部リンク)
-
-
はじめてのSQL:SELECT/WHERE/GROUP BYを最短で理解【コピペOK】
データ分析・自動レポート・簡易アプリの土台はSQLです。Pythonだけで押し切るより、前処理の7割をDB側で完結させる方が速く・安定します。本記事は、未経験〜初学者が週10時間×2〜3週で、SELE ...
-
-
【保存版】SQLite×Pythonで作る“ローカルDWH”——ETL・集計・レポート自動化の最短手順
ローカルでゼロ構築、ファイル1つで完結、サーバ不要。本記事はSQLite×Pythonで“毎日回る”ETL・集計・レポート自動化を最短で作るための完全ガイドです。データ設計→DB作成→ETL(取り込み ...
-
-
【実務で差がつく】pandas実践:欠損処理・結合・ウィンドウ関数・時系列・品質保証まで“読みやすく速い”型を習得
リード(結論)基礎を終えたら次は実務の現場で頻出する処理を“型”で覚える段階です。本記事は、pandas 2.x を前提に、欠損・外れ値・結合・ウィンドウ関数・時系列・カテゴリ処理・集計の自動化・大規 ...
-
-
コピペで回るレポート納品|Jupyter→PDF/HTML→共有の自動化テンプレ
毎週のレポート納品、朝にバタつきませんか? コードや図表は作ったのに、PDF化や共有で崩れる…。その“揺らぎ”を今日で終わらせましょう。 分析の価値は、最後の“納品物”で決まります。本記事では、Jup ...
-
-
未経験からデータサイエンティストへ:6ヶ月ロードマップ【現役が解説】
「数学もPythonもゼロだけど、半年で実務に通じる力はつく?」 結論、週10時間×24週の積み上げで「面接で語れる実務再現ポートフォリオ」まで到達できます。要は、学ぶ順番と迷わない設計です。 本記事 ...
最近のコメント