STEP 4:SQLによるデータ抽出

🔍 STEP 4: SQLによるデータ抽出

SELECT文をマスターして効率的にデータを取得する方法を学びます

📋 このステップで学ぶこと

  • SELECT文の基本構文と実践的な使い方
  • WHERE句による様々な条件指定(比較、範囲、パターン)
  • JOINを使った複数テーブルの結合
  • ORDER BY、GROUP BY、LIMIT による結果の加工
  • 増分抽出(Incremental Extract)の考え方と実装
  • ETLで使える実践的なSQLパターン

🎯 1. SELECT文の基本

1-1. SELECT文とは?

SELECT文は、データベースからデータを取得(抽出)するためのSQL文です。
ETLの「E(Extract:抽出)」において、最も重要で頻繁に使う構文です。

📚 例え話:図書館で本を探す

図書館で本を探すときのことを考えてみましょう:

「本を探して」 → SELECT(何を取得するか)
「小説コーナーから」 → FROM(どのテーブルから)
「推理小説だけ」 → WHERE(条件で絞り込み)
「著者名順に」 → ORDER BY(並び順)
「10冊だけ」 → LIMIT(取得件数制限)

1-2. SELECT文の基本構造

SELECT文は、以下の順序で記述します。

【SELECT文の基本構造】 SELECT カラム名 — 何を取得するか FROM テーブル名 — どのテーブルから WHERE 条件 — どんな条件で絞り込むか(省略可) ORDER BY 並び順 — どの順番で並べるか(省略可) LIMIT 件数; — 何件取得するか(省略可)
📝 SQLの記述ルール
  • SQLの命令は大文字でも小文字でもOK(SELECT = select)
  • ただし、大文字で書くのが慣習(読みやすい)
  • 文の最後にはセミコロン(;)をつける
  • コメント--で始める(その行の残りがコメント)

1-3. すべてのカラムを取得する

— * はすべてのカラムを意味する(ワイルドカード) SELECT * FROM users;
【実行結果】 user_id | name | email | created_at ——–|———–|——————–|———————– 1 | 山田太郎 | yamada@example.com | 2024-01-10 09:00:00 2 | 佐藤花子 | sato@example.com | 2024-01-11 14:30:00 3 | 鈴木一郎 | suzuki@example.com | 2024-01-12 10:15:00
📝 このSQLの意味
  • SELECT *:すべてのカラムを取得する
  • FROM users:usersテーブルから
  • *(アスタリスク)は「全部」という意味

1-4. 特定のカラムだけを取得する

— nameとemailだけを取得 SELECT name, email FROM users;
【実行結果】 name | email ———-|——————– 山田太郎 | yamada@example.com 佐藤花子 | sato@example.com 鈴木一郎 | suzuki@example.com
⚠️ SELECT * は避けるべき?

学習時やテスト時SELECT *でOKですが、本番環境では避けましょう。

  • 不要なカラムまで取得するため遅い
  • ネットワークの帯域を無駄に使う
  • 後からカラムが追加されると予期しない動作になる

ベストプラクティス:必要なカラムだけを明示的に指定する

1-5. カラムに別名(エイリアス)をつける

ASを使うと、カラム名に別名をつけることができます。
結果の可読性を高めたり、後の処理で扱いやすくするために使います。

— ASで別名をつける SELECT name AS 顧客名, email AS メールアドレス, created_at AS 登録日 FROM users;
【実行結果】 顧客名 | メールアドレス | 登録日 ———-|———————|———————- 山田太郎 | yamada@example.com | 2024-01-10 09:00:00 佐藤花子 | sato@example.com | 2024-01-11 14:30:00

1-6. 計算結果をカラムとして取得する

SELECT文の中で計算を行い、その結果を取得することもできます。

— 価格と数量から合計金額を計算 SELECT product_name, price, quantity, price * quantity AS total_amount — 計算結果に別名をつける FROM order_details;
【実行結果】 product_name | price | quantity | total_amount ————-|——–|———-|————- ノートPC | 89800 | 2 | 179600 マウス | 1980 | 5 | 9900 キーボード | 4500 | 3 | 13500

1-7. 重複を除外する(DISTINCT)

DISTINCTを使うと、重複したデータを除外して取得できます。

— 都市名の一覧を取得(重複なし) SELECT DISTINCT city FROM users;
【実行結果】 city ——– 東京 大阪 福岡 名古屋
📝 DISTINCTの使いどころ
  • 「どんな値があるか」を確認したいとき
  • マスターデータのリストを作りたいとき
  • カテゴリや地域などの一覧を取得したいとき

🔎 2. WHERE句による絞り込み

2-1. WHERE句とは?

WHERE句は、条件に合うデータだけを絞り込んで取得するために使います。
ETLでは、必要なデータだけを効率的に取得するために必須の機能です。

2-2. 基本的な比較演算子

演算子 意味
= 等しい WHERE status = 'active'
!= または <> 等しくない WHERE status != 'deleted'
> より大きい WHERE price > 1000
>= 以上 WHERE price >= 1000
< より小さい WHERE price < 1000
<= 以下 WHERE price <= 1000
-- 価格が1000円以上の商品を取得 SELECT * FROM products WHERE price >= 1000; -- カテゴリが「食品」の商品を取得 SELECT * FROM products WHERE category = '食品';

2-3. 複数条件の組み合わせ(AND、OR)

AND:両方の条件を満たす

-- 価格が1000円以上 かつ 5000円以下の商品 SELECT * FROM products WHERE price >= 1000 AND price <= 5000;
📝 ANDの意味

ANDは「かつ」という意味です。
両方の条件を満たすデータだけが取得されます。

OR:どちらかの条件を満たす

-- カテゴリが「食品」または「飲料」の商品 SELECT * FROM products WHERE category = '食品' OR category = '飲料';
📝 ORの意味

ORは「または」という意味です。
どちらかの条件を満たすデータが取得されます。

ANDとORの組み合わせ

-- カテゴリが「食品」または「飲料」で、かつ価格が500円未満 SELECT * FROM products WHERE (category = '食品' OR category = '飲料') AND price < 500;
⚠️ 括弧の重要性

ANDとORを組み合わせる場合は、括弧で優先順位を明示しましょう。
括弧がないと、予期しない結果になることがあります。

ルール:ANDはORより優先されます(数学の掛け算と足し算と同じ)

2-4. BETWEEN:範囲指定

BETWEENを使うと、範囲を簡潔に指定できます。

-- 価格が1000円以上5000円以下(両端を含む) SELECT * FROM products WHERE price BETWEEN 1000 AND 5000; -- これは以下と同じ意味 SELECT * FROM products WHERE price >= 1000 AND price <= 5000;
📝 BETWEENのポイント
  • BETWEENは両端の値を含む(以上・以下)
  • 数値だけでなく、日付にも使える
  • コードがシンプルになるので、範囲指定には積極的に使いましょう

2-5. IN:複数の値に一致

INを使うと、複数の値のいずれかに一致するデータを取得できます。

-- カテゴリが「食品」「飲料」「お菓子」のいずれかの商品 SELECT * FROM products WHERE category IN ('食品', '飲料', 'お菓子'); -- これは以下と同じ(INの方がスッキリ) SELECT * FROM products WHERE category = '食品' OR category = '飲料' OR category = 'お菓子';
✅ INの使いどころ
  • 特定のIDリストに該当するデータを取得したいとき
  • 複数のカテゴリを指定したいとき
  • ORを何度も書くより読みやすくなる

2-6. LIKE:パターンマッチング

LIKEを使うと、文字列の部分一致でデータを検索できます。

パターン 意味
% 0文字以上の任意の文字列 '山%' → 山、山田、山本太郎
_ 任意の1文字 '山_' → 山田、山本(2文字のみ)
-- 「山」で始まる名前 SELECT * FROM users WHERE name LIKE '山%'; -- 結果:山田太郎、山本花子、山口次郎 -- 「田」で終わる名前 SELECT * FROM users WHERE name LIKE '%田'; -- 結果:山田、内田、田 -- 「田」を含む名前 SELECT * FROM users WHERE name LIKE '%田%'; -- 結果:山田太郎、田中一郎、内田美咲 -- 3文字の名前 SELECT * FROM users WHERE name LIKE '___'; -- 結果:山田太、佐藤花、鈴木一(3文字のみ)

2-7. NULL値の扱い

NULLは「値がない」ことを表す特別な値です。
NULLの判定には、=ではなくIS NULLを使います。

-- メールアドレスが設定されていないユーザー SELECT * FROM users WHERE email IS NULL; -- メールアドレスが設定されているユーザー SELECT * FROM users WHERE email IS NOT NULL;
⚠️ NULLの比較に注意!

= NULL使えません!必ずIS NULLを使いましょう。

  • ❌ 間違い:WHERE email = NULL(動作しない)
  • ✅ 正しい:WHERE email IS NULL

2-8. 日付の条件指定(ETLで頻出)

ETLでは、日付範囲でデータを絞り込むことが非常に多いです。

-- 2024年1月のデータを取得 SELECT * FROM orders WHERE order_date >= '2024-01-01' AND order_date < '2024-02-01'; -- 昨日のデータを取得(PostgreSQL) SELECT * FROM orders WHERE order_date >= CURRENT_DATE - INTERVAL '1 day' AND order_date < CURRENT_DATE; -- 過去30日間のデータを取得 SELECT * FROM orders WHERE order_date >= CURRENT_DATE - INTERVAL '30 days'; -- 今日のデータを取得 SELECT * FROM orders WHERE order_date >= CURRENT_DATE AND order_date < CURRENT_DATE + INTERVAL '1 day';
📝 日付範囲指定のポイント
  • 開始日は「>=」終了日は「<」を使うのがベストプラクティス
  • 「<」を使うことで、境界の重複を防ぐ
  • CURRENT_DATEは今日の日付を返す関数
  • INTERVAL '1 day'は「1日間」を意味する

📊 3. ORDER BY、GROUP BY、LIMIT

3-1. ORDER BY:結果を並び替える

ORDER BYを使うと、結果を指定したカラムで並び替えることができます。

-- 価格の安い順(昇順:ASC) SELECT * FROM products ORDER BY price ASC; -- 価格の高い順(降順:DESC) SELECT * FROM products ORDER BY price DESC; -- 複数のカラムで並び替え(カテゴリ順、その中で価格順) SELECT * FROM products ORDER BY category ASC, price DESC;
📝 ORDER BYのポイント
  • ASC:昇順(小さい順、A→Z、古い順)。省略時のデフォルト
  • DESC:降順(大きい順、Z→A、新しい順)
  • 複数カラム指定時は、左から順に優先される

3-2. LIMIT:取得件数を制限する

LIMITを使うと、取得するデータの件数を制限できます。

-- 最初の10件だけ取得 SELECT * FROM products LIMIT 10; -- 価格が高い順で上位5件を取得 SELECT * FROM products ORDER BY price DESC LIMIT 5; -- 11件目から20件目を取得(ページネーション) SELECT * FROM products ORDER BY product_id LIMIT 10 OFFSET 10; -- 10件スキップして10件取得
✅ LIMITの使いどころ
  • テスト時:大量データの一部だけを確認したいとき
  • ページネーション:一覧表示で1ページ分だけ取得
  • ランキング:上位N件を取得
  • パフォーマンス:不要なデータを取得しない

3-3. GROUP BY:集計する

GROUP BYを使うと、データをグループ化して集計できます。

-- カテゴリ別の商品数を集計 SELECT category, COUNT(*) AS product_count FROM products GROUP BY category; -- カテゴリ別の平均価格を集計 SELECT category, AVG(price) AS avg_price, MAX(price) AS max_price, MIN(price) AS min_price FROM products GROUP BY category;
【実行結果】 category | product_count ---------|--------------- 食品 | 150 飲料 | 80 家電 | 45

よく使う集計関数

関数 意味
COUNT(*) 行数を数える COUNT(*) → 150
SUM() 合計 SUM(price) → 1250000
AVG() 平均 AVG(price) → 2500
MAX() 最大値 MAX(price) → 89800
MIN() 最小値 MIN(price) → 100

3-4. HAVING:集計結果を絞り込む

HAVINGは、GROUP BYで集計した結果を絞り込むために使います。

-- 商品数が10以上のカテゴリだけを表示 SELECT category, COUNT(*) AS product_count FROM products GROUP BY category HAVING COUNT(*) >= 10;
📝 WHEREとHAVINGの違い
  • WHERE集計前のデータを絞り込む
  • HAVING集計後の結果を絞り込む

例:「価格が1000円以上の商品」で「カテゴリ別に集計」して「商品数が5以上のカテゴリ」を表示

-- WHERE(集計前の絞り込み)とHAVING(集計後の絞り込み)の組み合わせ SELECT category, COUNT(*) AS product_count, AVG(price) AS avg_price FROM products WHERE price >= 1000 -- 集計前:1000円以上の商品だけを対象 GROUP BY category HAVING COUNT(*) >= 5 -- 集計後:商品数5以上のカテゴリだけ表示 ORDER BY avg_price DESC;

🔗 4. JOINを使った複数テーブル抽出

4-1. JOINとは?

JOINは、複数のテーブルを結合してデータを取得する方法です。
ETLでは、複数のデータソースを組み合わせて分析用データを作るために、非常によく使います。

📊 例:ECサイトの3つのテーブル

以下の3つのテーブルがあるとします:

【usersテーブル】ユーザー情報 user_id | name | email --------|-----------|---------------------- 1 | 山田太郎 | yamada@example.com 2 | 佐藤花子 | sato@example.com 3 | 鈴木一郎 | suzuki@example.com 【productsテーブル】商品情報 product_id | product_name | price | category -----------|--------------|--------|---------- 1001 | ノートPC | 89800 | 家電 1002 | マウス | 1980 | 家電 1003 | コーヒー | 350 | 飲料 【ordersテーブル】注文情報 order_id | user_id | product_id | quantity | order_date ---------|---------|------------|----------|------------ 101 | 1 | 1001 | 1 | 2024-01-15 102 | 1 | 1002 | 2 | 2024-01-15 103 | 2 | 1003 | 3 | 2024-01-16

これらを結合して、「誰が、いつ、何を、いくつ買ったか」を一度に取得したい!

4-2. INNER JOIN:両方に存在するデータのみ

INNER JOINは、両方のテーブルにデータが存在する場合のみ結合します。
最もよく使うJOINです。

-- ordersテーブルにusersとproductsを結合 SELECT o.order_id, o.order_date, u.name AS customer_name, p.product_name, p.price, o.quantity, (p.price * o.quantity) AS total_amount FROM orders o INNER JOIN users u ON o.user_id = u.user_id INNER JOIN products p ON o.product_id = p.product_id;
【実行結果】 order_id | order_date | customer_name | product_name | price | quantity | total_amount ---------|------------|---------------|--------------|-------|----------|------------- 101 | 2024-01-15 | 山田太郎 | ノートPC | 89800 | 1 | 89800 102 | 2024-01-15 | 山田太郎 | マウス | 1980 | 2 | 3960 103 | 2024-01-16 | 佐藤花子 | コーヒー | 350 | 3 | 1050
📝 JOINの構文を分解して理解する

① テーブルに別名をつける

  • orders o:ordersテーブルを「o」という短い名前で使う
  • users u:usersテーブルを「u」という短い名前で使う
  • products p:productsテーブルを「p」という短い名前で使う

② ON句で結合条件を指定

  • ON o.user_id = u.user_id:ordersのuser_idとusersのuser_idが一致するものを結合
  • ON o.product_id = p.product_id:ordersのproduct_idとproductsのproduct_idが一致するものを結合

③ カラム名を「テーブル別名.カラム名」で指定

  • o.order_id:ordersテーブルのorder_id
  • u.name:usersテーブルのname

4-3. LEFT JOIN:左のテーブルはすべて表示

LEFT JOINは、左側のテーブルのデータはすべて表示し、右側のテーブルに対応するデータがない場合はNULLになります。

-- すべてのユーザーを表示(注文していないユーザーも含む) SELECT u.user_id, u.name, o.order_id, o.order_date FROM users u LEFT JOIN orders o ON u.user_id = o.user_id;
【実行結果】 user_id | name | order_id | order_date --------|-----------|----------|------------ 1 | 山田太郎 | 101 | 2024-01-15 1 | 山田太郎 | 102 | 2024-01-15 2 | 佐藤花子 | 103 | 2024-01-16 3 | 鈴木一郎 | NULL | NULL ← 注文していないユーザー
✅ LEFT JOINの使いどころ
  • 全ユーザーの一覧を表示して、注文があれば表示」したいとき
  • 全商品の一覧を表示して、売上があれば表示」したいとき
  • 「対応するデータがない場合も含めて分析」したいとき

4-4. JOINの種類まとめ

JOIN種類 説明 使用例
INNER JOIN 両方のテーブルに存在するデータのみ 注文と顧客を結合
(注文がある顧客のみ)
LEFT JOIN 左のテーブルはすべて表示
右にない場合はNULL
全顧客を表示
(注文なしも含む)
RIGHT JOIN 右のテーブルはすべて表示
左にない場合はNULL
LEFT JOINの逆
(あまり使わない)
FULL OUTER JOIN 両方のテーブルのすべてのデータ まれに使う
【JOINの図解】 INNER JOIN:共通部分のみ ┌─────────┬─────────┐ │ LEFT │ RIGHT │ │ ┌────┼────┐ │ │ │ ●●●●●● │ │ ← この部分だけ取得 │ └────┼────┘ │ └─────────┴─────────┘ LEFT JOIN:左すべて+共通部分 ┌─────────┬─────────┐ │ LEFT │ RIGHT │ │ ●●●●●●●●●●●● │ │ ← 左は全部、右はマッチするものだけ │ └────┼────┘ │ └─────────┴─────────┘

📈 5. 増分抽出の考え方

5-1. 増分抽出とは?

増分抽出(Incremental Extract)とは、前回以降に追加・更新されたデータだけを取得する方法です。
ETLパイプラインでは、効率的にデータを取得するために非常に重要な概念です。

📰 例え話:新聞配達

全量抽出:毎日、過去の新聞も含めて全部配達する
→ 大量の新聞を運ぶ必要があり、非効率!

増分抽出今日の新聞だけを配達する
→ 1部だけ運べばいいので、効率的!

5-2. 全量抽出 vs 増分抽出

❌ 全量抽出の問題点
  • 毎回すべてのデータを取得
  • データが増えるとどんどん遅くなる
  • データベースに大きな負荷がかかる
  • ネットワーク転送量が膨大になる
  • 100万件 → 1時間かかることも
✅ 増分抽出のメリット
  • 新しいデータだけを取得
  • 処理時間が大幅に短縮
  • データベースへの負荷が軽い
  • ネットワーク転送量が少ない
  • 1000件だけなら数秒で完了
【全量抽出 vs 増分抽出の比較】 ■ 全量抽出(毎日すべてのデータを取得) 1日目:100万件取得(1時間) 2日目:100万件取得(1時間) 3日目:100万件取得(1時間) → 毎日同じデータを何度も取得している... ■ 増分抽出(前日の新規データだけを取得) 1日目:100万件取得(初回は全量) 2日目:1,000件取得(前日の新規分だけ)← 数秒で完了! 3日目:1,200件取得(前日の新規分だけ)← 数秒で完了! → 効率的!

5-3. 増分抽出の実装方法

方法1:タイムスタンプを使う(最も一般的)

created_at(作成日時)やupdated_at(更新日時)カラムを使って、
前回以降のデータだけを取得します。

-- 昨日以降に作成されたデータを取得 SELECT * FROM orders WHERE created_at >= CURRENT_DATE - INTERVAL '1 day'; -- 特定の日時以降のデータを取得 SELECT * FROM orders WHERE created_at > '2024-01-15 23:59:59'; -- 更新されたデータも含めて取得 SELECT * FROM orders WHERE updated_at > '2024-01-15 23:59:59';

方法2:IDを使う

連番のID(AUTO INCREMENT)を使って、前回取得した最大IDより大きいデータを取得します。

-- 前回取得した最大IDより大きいデータを取得 SELECT * FROM orders WHERE order_id > 12345 ORDER BY order_id;

5-4. Pythonでの増分抽出の実装

増分抽出をPythonで実装するには、「前回の実行日時を記録して、次回に使う」という仕組みが必要です。

ステップ1:前回実行日時を読み込む

import json def load_last_run_time(): """前回実行日時をファイルから読み込む""" try: with open('last_run.json', 'r') as f: data = json.load(f) return data['last_run_time'] except FileNotFoundError: # ファイルがない場合は初回実行 return None

ステップ2:今回の実行日時を保存する

from datetime import datetime def save_current_run_time(): """今回の実行日時をファイルに保存する""" current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') with open('last_run.json', 'w') as f: json.dump({'last_run_time': current_time}, f)

ステップ3:増分抽出のメイン処理

import psycopg2 import pandas as pd def extract_incremental_data(): """増分抽出を実行する""" # 前回実行日時を取得 last_run_time = load_last_run_time() # DB接続 conn = psycopg2.connect( host="localhost", database="mydb", user="postgres", password="password" ) if last_run_time is None: # 初回は全量抽出 print("初回実行:全量抽出します") query = "SELECT * FROM orders" else: # 2回目以降は増分抽出 print(f"増分抽出:{last_run_time} 以降のデータ") query = f""" SELECT * FROM orders WHERE created_at > '{last_run_time}' """ # データ取得 df = pd.read_sql_query(query, conn) conn.close() print(f"取得件数: {len(df)}件") # 今回の実行日時を保存(次回の増分抽出用) save_current_run_time() return df

完成コード:増分抽出スクリプト

# ===== 増分抽出の完成コード ===== import json import psycopg2 import pandas as pd from datetime import datetime # 設定ファイルのパス LAST_RUN_FILE = 'last_run.json' def load_last_run_time(): """前回実行日時を読み込む""" try: with open(LAST_RUN_FILE, 'r') as f: data = json.load(f) return data.get('last_run_time') except FileNotFoundError: return None def save_current_run_time(run_time): """今回の実行日時を保存する""" with open(LAST_RUN_FILE, 'w') as f: json.dump({'last_run_time': run_time}, f) def extract_orders(): """注文データを増分抽出する""" # 現在時刻を記録(処理開始時点) current_run_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') # 前回実行日時を取得 last_run_time = load_last_run_time() # DB接続設定 db_config = { 'host': 'localhost', 'database': 'mydb', 'user': 'postgres', 'password': 'password' } try: # DB接続 with psycopg2.connect(**db_config) as conn: if last_run_time is None: # 初回:全量抽出 print("【初回実行】全量抽出を実行します") query = "SELECT * FROM orders ORDER BY order_id" else: # 2回目以降:増分抽出 print(f"【増分抽出】{last_run_time} 以降のデータを取得します") query = f""" SELECT * FROM orders WHERE created_at > '{last_run_time}' ORDER BY order_id """ # データ取得 df = pd.read_sql_query(query, conn) print(f"取得件数: {len(df)}件") # 成功したら実行日時を保存 save_current_run_time(current_run_time) return df except Exception as e: print(f"エラー: {e}") return pd.DataFrame() # 実行 if __name__ == '__main__': df = extract_orders() print(df.head())
💡 増分抽出の設計ポイント
  • created_atカラム:データ作成日時(必須)
  • updated_atカラム:データ更新日時(UPDATE対応には必要)
  • 最終実行日時の記録:ファイルやDBに保存して次回に使う
  • 初回は全量抽出:2回目以降が増分抽出
  • 定期的に全量抽出:データの整合性確認のため(月1回など)

📝 STEP 4 のまとめ

✅ このステップで学んだこと
  • SELECT文:データを取得する基本構文、AS で別名、DISTINCT で重複除外
  • WHERE句:条件で絞り込み(=, >, <, BETWEEN, IN, LIKE, IS NULL)
  • AND/OR:複数条件の組み合わせ(括弧で優先順位を明示)
  • ORDER BY:結果の並び替え(ASC/DESC)
  • GROUP BY:集計(COUNT, SUM, AVG, MAX, MIN)
  • JOIN:複数テーブルの結合(INNER JOIN, LEFT JOIN)
  • 増分抽出:前回以降のデータだけを効率的に取得
💡 実務でのポイント

1. SELECT * は避ける
必要なカラムだけを明示的に指定しましょう。

2. 日付範囲は「>=」と「<」を使う
境界の重複を防ぐベストプラクティスです。

3. 増分抽出を基本にする
大量データを毎回全量取得すると、パフォーマンスが劣化します。

🎯 次のステップの予告

次のSTEP 5では、「API・Webスクレイピング基礎」を学びます。

  • REST APIの呼び出し方
  • JSONレスポンスの処理
  • ページネーションの対応
  • Beautiful Soupを使ったWebスクレイピング

データベース以外のデータソースからデータを取得する方法を習得しましょう!

📝 練習問題

問題 1 基礎

usersテーブルから、nameとemailだけを取得するSQLを書いてください。

【解答】
SELECT name, email FROM users;
問題 2 基礎

productsテーブルから、価格が1000円以上5000円以下のデータを取得してください。

【解答】
-- 方法1:BETWEENを使う SELECT * FROM products WHERE price BETWEEN 1000 AND 5000; -- 方法2:ANDを使う SELECT * FROM products WHERE price >= 1000 AND price <= 5000;
問題 3 基礎

usersテーブルから、名前が「田」で終わる人を取得してください。

【解答】
SELECT * FROM users WHERE name LIKE '%田';
問題 4 基礎

productsテーブルから、カテゴリが「食品」「飲料」「お菓子」のいずれかの商品を取得してください。

【解答】
SELECT * FROM products WHERE category IN ('食品', '飲料', 'お菓子');
問題 5 応用

ordersテーブルとusersテーブルを結合して、注文ID、注文日、顧客名を取得してください。

【解答】
SELECT o.order_id, o.order_date, u.name AS customer_name FROM orders o INNER JOIN users u ON o.user_id = u.user_id;
問題 6 応用

2024年1月のデータだけを取得するSQLを書いてください。

【解答】
SELECT * FROM orders WHERE order_date >= '2024-01-01' AND order_date < '2024-02-01';
問題 7 応用

カテゴリ別の商品数と平均価格を集計してください。商品数の多い順に並べてください。

【解答】
SELECT category, COUNT(*) AS product_count, AVG(price) AS avg_price FROM products GROUP BY category ORDER BY product_count DESC;
問題 8 応用

すべてのユーザーと、その注文情報を表示してください。注文していないユーザーも表示すること。

【解答】
SELECT u.user_id, u.name, o.order_id, o.order_date FROM users u LEFT JOIN orders o ON u.user_id = o.user_id;
問題 9 発展

昨日以降に追加されたデータを取得する増分抽出SQLを書いてください。

【解答】
SELECT * FROM orders WHERE created_at >= CURRENT_DATE - INTERVAL '1 day' ORDER BY created_at;
問題 10 発展

注文テーブル、ユーザーテーブル、商品テーブルを結合し、顧客名、商品名、数量、合計金額(価格×数量)を取得してください。2024年1月のデータだけを対象とし、合計金額の高い順に上位10件を取得してください。

【解答】
SELECT u.name AS customer_name, p.product_name, o.quantity, (p.price * o.quantity) AS total_amount FROM orders o INNER JOIN users u ON o.user_id = u.user_id INNER JOIN products p ON o.product_id = p.product_id WHERE o.order_date >= '2024-01-01' AND o.order_date < '2024-02-01' ORDER BY total_amount DESC LIMIT 10;
📝

学習メモ

ETL・データパイプライン構築 - Step 4

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE