ããŒã¿ã¢ããªã¹ãã®ããã®SQLïŒãŠã£ã³ããŠé¢æ°ãCTEãé«åºŠãªã¯ãšãªææ³
SQLã®ãŠã£ã³ããŠé¢æ°ãCTEïŒå ±éããŒãã«åŒïŒãé«åºŠãªåæã¯ãšãªãã³ãŒãäŸä»ãã§è§£èª¬ãããŒã¿ã¢ããªã¹ã颿¥å¯Ÿçãšå®åã«çŽçµããå¿ é ãã¯ããã¯ã

SQLã®ãŠã£ã³ããŠé¢æ°ãCTEïŒå ±éããŒãã«åŒïŒãé«åºŠãªã¯ãšãªãã¿ãŒã³ã¯ãåæSQLã®åºç€ãæ§æããèŠçŽ ã§ããããŒã¿ã¢ããªã¹ã颿¥ã®æºåã§ãã£ãŠããè€éãªã¬ããŒãã£ã³ã°ã¯ãšãªãžã®å¯Ÿå¿ã§ãã£ãŠãããããã®ãã¯ããã¯ãç¿åŸããããšã§ãåé·ã§å¯èªæ§ã®äœããµãã¯ãšãªããç°¡æœã§ããã©ãŒãã³ã¹ã®é«ãSQLã«å€æã§ããŸãã
ãŠã£ã³ããŠé¢æ°ã¯ãçŸåšã®è¡ã«é¢é£ããè¡ã®éåã«å¯ŸããŠèšç®ãå®è¡ããŸããGROUP BYã®ããã«çµæã1è¡ã«éçŽããã®ã§ã¯ãªããåè¡ããã®ãŸãŸä¿æãããŸãŸèšç®çµæãä»å ã§ããç¹ãç¹åŸŽã§ããCTEãšçµã¿åãããããšã§ãè€éãªåæã¯ãšãªãèªã¿ãããä¿å®ãããã圢ã«ãŸãšããããšãã§ããŸãã
SQLãŠã£ã³ããŠé¢æ°ãšOVERå¥ã®åºæ¬
ãŠã£ã³ããŠé¢æ°ã¯ãå®çŸ©ãããããŠã£ã³ããŠãïŒè¡ã®ç¯å²ïŒã«å¯ŸããŠèšç®ãé©çšããŸããOVERå¥ããã®ãŠã£ã³ããŠã«å«ãŸããè¡ãšãè¡ã®äžŠã³é ãå¶åŸ¡ããŸããGROUP BYã䜿ã£ãéçŽé¢æ°ãšã¯ç°ãªãããŠã£ã³ããŠé¢æ°ã¯çµæã»ããã®åè¡ããã¹ãŠä¿æããŸãã
以äžã®æ§æã¯ãPostgreSQLãMySQL 8以éãBigQueryãSQL ServerãSnowflakeãªã©ãäž»èŠãªããŒã¿ããŒã¹ã§å ±éããŠäœ¿çšã§ããŸãã
-- window_function_syntax.sql
SELECT
employee_id,
department,
salary,
-- Ranks employees within each department by salary
RANK() OVER (
PARTITION BY department
ORDER BY salary DESC
) AS dept_salary_rank,
-- Running total of salaries within department
SUM(salary) OVER (
PARTITION BY department
ORDER BY salary DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS running_salary_total
FROM employees;PARTITION BYã¯ããŒã¿ãã°ã«ãŒãã«åå²ããŸãïŒGROUP BYã«é¡äŒŒããŸãããè¡ãéçŽããŸããïŒãORDER BYã¯åããŒãã£ã·ã§ã³å ã®é åºãå®çŸ©ããŸãããªãã·ã§ã³ã®ãã¬ãŒã å¥ïŒROWS BETWEEN ...ïŒã¯ããŠã£ã³ããŠãç¹å®ã®è¡ã®ç¯å²ã«éå®ããŸãã
ROW_NUMBERãRANKãDENSE_RANKã®æ¯èŒ
ããã3ã€ã®ã©ã³ãã³ã°é¢æ°ã¯èŠãç®ã䌌ãŠããŸãããåé äœïŒã¿ã€ïŒãååšããå Žåã®æåãç°ãªããŸãã誀ã£ã颿°ãéžæããããšã¯ãåæã¯ãšãªã«ããããã°ã®é »åºåå ã®ã²ãšã€ã§ãã
-- ranking_comparison.sql
SELECT
product_name,
category,
revenue,
ROW_NUMBER() OVER (ORDER BY revenue DESC) AS row_num,
RANK() OVER (ORDER BY revenue DESC) AS rank_val,
DENSE_RANK() OVER (ORDER BY revenue DESC) AS dense_rank_val
FROM products;| product_name | revenue | row_num | rank_val | dense_rank_val |
|---|---|---|---|---|
| Widget A | 50000 | 1 | 1 | 1 |
| Widget B | 50000 | 2 | 1 | 1 |
| Widget C | 40000 | 3 | 3 | 2 |
| Widget D | 30000 | 4 | 4 | 3 |
ROW_NUMBERã¯åžžã«äžæã®é£çªãå²ãåœãŠãŸããåãå€ã®è¡ãååšããå Žåã§ããããããã®è¡ã«ä»»æã«å°ããçªå·ãä»äžãããŸããRANKã¯åé äœã®è¡ã«åãçªå·ãå²ãåœãŠãŸãããåŸç¶ã®çªå·ãé£ã°ããŸãïŒ1, 1, 3ïŒãDENSE_RANKãåé äœãåŠçããŸãããçªå·ãé£ã°ããŸããïŒ1, 1, 2ïŒãäžäœNä»¶ã®ã¯ãšãªã§éè€ããå€ãåãé äœãå ±æãã¹ãå Žåã¯ãDENSE_RANKãé©åãªéžæã§ãã
LAGãšLEADã«ããæéæ¯èŒåæ
LAGãšLEADã¯ãã»ã«ããžã§ã€ã³ã䜿ããã«ãååŸã®è¡ã®ããŒã¿ã«ã¢ã¯ã»ã¹ã§ããŸããåææ¯ã®æé·çèšç®ããã¬ã³ãæ€åºãå€åã®ç¹å®ã«äžå¯æ¬ ãªé¢æ°ã§ãã
-- period_over_period.sql
SELECT
month,
revenue,
-- Previous month revenue
LAG(revenue, 1) OVER (ORDER BY month) AS prev_month_revenue,
-- Month-over-month growth rate
ROUND(
(revenue - LAG(revenue, 1) OVER (ORDER BY month)) * 100.0
/ NULLIF(LAG(revenue, 1) OVER (ORDER BY month), 0),
2
) AS mom_growth_pct,
-- Next month revenue (forward-looking)
LEAD(revenue, 1) OVER (ORDER BY month) AS next_month_revenue
FROM monthly_sales
ORDER BY month;LAG/LEADã®ç¬¬2åŒæ°ã¯ãªãã»ããïŒããã©ã«ãã¯1ïŒãæå®ããŸãã第3åŒæ°ïŒãªãã·ã§ã³ïŒã¯ã該åœãªãã»ããã«è¡ãååšããªãå Žåã®ããã©ã«ãå€ãæå®ã§ããå é è¡ãæ«å°Ÿè¡ã§ã®NULLåé¿ã«æå¹ã§ããæé·çèšç®ã®NULLIFã¯ããŒãé€ç®ãšã©ãŒã鲿¢ããŸãã
NTILEã«ããããŒã»ã³ã¿ã€ã«åå²
NTILEã¯ãæå®ããæ°ã®ã»ãŒçããã°ã«ãŒãã«è¡ãåé ããŸããããŒã¿ã¢ããªã¹ãã¯ååäœåæãååäœã¹ã³ã¢ãªã³ã°ã顧客ã»ã°ã¡ã³ããŒã·ã§ã³ã«ãã®é¢æ°ã掻çšããŸãã
-- customer_segmentation.sql
SELECT
customer_id,
total_spend,
-- Split customers into 4 quartiles by spend
NTILE(4) OVER (ORDER BY total_spend DESC) AS spend_quartile,
-- Decile scoring for finer granularity
NTILE(10) OVER (ORDER BY total_spend DESC) AS spend_decile
FROM (
SELECT
customer_id,
SUM(order_total) AS total_spend
FROM orders
WHERE order_date >= '2025-01-01'
GROUP BY customer_id
) customer_totals;ååäœ1ã«ã¯æãæ¯åºé¡ã®é«ã顧客ããååäœ4ã«ã¯æãäœã顧客ãå«ãŸããŸãããã®ãã¿ãŒã³ã¯ãããŒã±ãã£ã³ã°åæã§äœ¿çšãããRFMïŒRecencyãFrequencyãMonetaryïŒã»ã°ã¡ã³ããŒã·ã§ã³ã«çŽæ¥å¯Ÿå¿ããŠããŸãã
Data Analyticsã®é¢æ¥å¯Ÿçã¯ã§ããŠããŸããïŒ
ã€ã³ã¿ã©ã¯ãã£ããªã·ãã¥ã¬ãŒã¿ãŒãflashcardsãæè¡ãã¹ãã§ç·Žç¿ããŸãããã
å ±éããŒãã«åŒïŒCTEïŒïŒãã¹ãããããµãã¯ãšãªã®çœ®ãæã
CTEïŒWITHå¥ïŒã¯ãè€éãªã¯ãšãªãååä»ãã®èªã¿ãããã¹ãããã«åè§£ããŸããåCTEã¯ããã®ã¯ãšãªã®å®è¡æéäžã®ã¿ååšããäžæçãªååä»ãçµæã»ãããšããŠæ©èœããŸããå¯èªæ§ã®åäžã«å ããŠãåã¹ããããç¬ç«ããŠãã¹ãã§ããããããããã°ã容æã«ãªããŸãã
-- cte_sales_analysis.sql
WITH monthly_revenue AS (
-- Step 1: Aggregate raw orders into monthly totals
SELECT
DATE_TRUNC('month', order_date) AS month,
product_category,
SUM(amount) AS revenue,
COUNT(DISTINCT customer_id) AS unique_customers
FROM orders
WHERE order_date >= '2025-01-01'
GROUP BY DATE_TRUNC('month', order_date), product_category
),
ranked_categories AS (
-- Step 2: Rank categories within each month
SELECT
month,
product_category,
revenue,
unique_customers,
RANK() OVER (
PARTITION BY month
ORDER BY revenue DESC
) AS category_rank
FROM monthly_revenue
)
-- Step 3: Final output â top 3 categories per month
SELECT
month,
product_category,
revenue,
unique_customers,
category_rank
FROM ranked_categories
WHERE category_rank <= 3
ORDER BY month, category_rank;ãã®3ã¹ãããã®ã¢ãããŒãã¯ãæ·±ããã¹ãããããµãã¯ãšãªã®ä»£æ¿ãšããŠæ©èœããŸããåCTEã«ã¯æç¢ºãªè²¬ä»»ããããéçŽãã©ã³ãã³ã°ããã£ã«ã¿ãªã³ã°ã®åœ¹å²ãåé¢ãããŠããŸãã
ååž°CTEã«ããéå±€ããŒã¿ã®åŠç
ååž°CTEã¯ãéå±€æ§é ãã°ã©ãåã®ããŒã¿ã«é¢ããåé¡ã解決ããŸããçµç¹å³ãã«ããŽãªããªãŒãéšå衚ïŒBOMïŒãçµè·¯æ¢çŽ¢ã¯ãšãªãªã©ãå žåçãªãŠãŒã¹ã±ãŒã¹ã§ãã
-- recursive_org_chart.sql
WITH RECURSIVE org_hierarchy AS (
-- Base case: top-level managers (no manager above them)
SELECT
employee_id,
employee_name,
manager_id,
1 AS depth,
employee_name AS management_chain
FROM employees
WHERE manager_id IS NULL
UNION ALL
-- Recursive case: join employees to their managers
SELECT
e.employee_id,
e.employee_name,
e.manager_id,
oh.depth + 1,
oh.management_chain || ' > ' || e.employee_name
FROM employees e
INNER JOIN org_hierarchy oh ON e.manager_id = oh.employee_id
)
SELECT
employee_id,
employee_name,
depth,
management_chain
FROM org_hierarchy
ORDER BY management_chain;ããŒã¹ã±ãŒã¹ã¯ã«ãŒãããŒãïŒäžåžã®ããªãåŸæ¥å¡ïŒãéžæããŸããååž°ã±ãŒã¹ã¯CTEèªèº«ã«çµåããéå±€ãã¬ãã«ããšã«æ§ç¯ããŸããmanagement_chainåã¯ååãé£çµããå®å šãªå ±åãã¹ã衚瀺ããŸããã»ãšãã©ã®ããŒã¿ããŒã¹ã§ã¯ç¡éã«ãŒãã鲿¢ããããã«ååž°ã®æ·±ããå¶éãããŠãããPostgreSQLã®ããã©ã«ãã¯100åã§ãã
ååž°CTEã¯å€§èŠæš¡ãªããŒã¿ã»ããã§ã¯åŠçãé ããªãå¯èœæ§ããããŸããæ·±ãã®å¶éïŒWHERE depth < 10ïŒãå¿ ãå«ããçµååïŒmanager_idïŒã«ã€ã³ããã¯ã¹ãèšå®ãããŠããããšã確èªããŠãã ãããéåžžã«æ·±ãéå±€æ§é ã®å Žåã¯ããããªã¢ã©ã€ãºããã¹ããã¹ãããã»ãããã¿ãŒã³ã®æ¡çšãæ€èšããŠãã ããã
é«åºŠãªåæãã¿ãŒã³ïŒã®ã£ãããšã¢ã€ã©ã³ãã环èš
ã®ã£ãããšã¢ã€ã©ã³ããã¿ãŒã³ã¯ãããŒã¿å ã®é£ç¶ããã·ãŒã±ã³ã¹ãèå¥ããŸããã¢ã¯ãã£ããªãµãã¹ã¯ãªãã·ã§ã³æéãé£ç¶ãã°ã€ã³æ¥æ°ãéåãã®ãªã皌åæéãªã©ã該åœããŸãããã®ãã¯ããã¯ã¯ROW_NUMBERãšæ¥ä»æŒç®ãçµã¿åãããŸãã
-- consecutive_login_streaks.sql
WITH login_days AS (
SELECT DISTINCT
user_id,
DATE(login_timestamp) AS login_date
FROM user_sessions
),
streaks AS (
SELECT
user_id,
login_date,
-- Subtracting row_number from date creates a constant for consecutive days
login_date - (ROW_NUMBER() OVER (
PARTITION BY user_id
ORDER BY login_date
))::int AS streak_group
FROM login_days
)
SELECT
user_id,
MIN(login_date) AS streak_start,
MAX(login_date) AS streak_end,
COUNT(*) AS streak_length
FROM streaks
GROUP BY user_id, streak_group
HAVING COUNT(*) >= 3
ORDER BY streak_length DESC;ãã®ãã¯ããã¯ã®æ žå¿ã¯ãé£ç¶ããæ¥ä»ããå¢å ããè¡çªå·ãåŒããšãåžžã«åãå€ãåŸããããšããç¹ã«ãããŸããã®ã£ãããçºçãããšçµæã®å€ãå€åããæ°ããã°ã«ãŒãã圢æãããŸãããã®ã¯ãšãªã¯ããŠãŒã¶ãŒããšã«3æ¥ä»¥äžã®é£ç¶ãã°ã€ã³ã¹ããªãŒã¯ããã¹ãŠæ€åºããŸãã
ãŠã£ã³ããŠé¢æ°ãšCASEåŒã®çµã¿åããã«ããæ¡ä»¶ä»ãåæ
å®åã®åæã¯ãšãªã§ã¯ããŠã£ã³ããŠé¢æ°ãšCASEåŒãçµã¿åãããŠãåäžã¯ãšãªå ã§æ¡ä»¶ä»ãã¡ããªã¯ã¹ãèšç®ããããšãé »ç¹ã«ãããŸãã
-- conditional_analytics.sql
SELECT
order_date,
product_category,
amount,
-- 7-day moving average
AVG(amount) OVER (
PARTITION BY product_category
ORDER BY order_date
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
) AS moving_avg_7d,
-- Cumulative sum resetting each quarter
SUM(amount) OVER (
PARTITION BY product_category, DATE_TRUNC('quarter', order_date)
ORDER BY order_date
) AS qtd_cumulative,
-- Flag if current row exceeds 2x the category average
CASE
WHEN amount > 2 * AVG(amount) OVER (PARTITION BY product_category)
THEN 'OUTLIER'
ELSE 'NORMAL'
END AS outlier_flag
FROM daily_sales
ORDER BY product_category, order_date;ãã®åäžã®ã¯ãšãªã§ã7æ¥éç§»åå¹³åãååæããšã«ãªã»ããããã环èšãå€ãå€ãã©ã°ã®3ã€ãåæã«èšç®ã§ããŸãããµãã¯ãšãªãã»ã«ããžã§ã€ã³ã¯äžåäžèŠã§ãã
ãŠã£ã³ããŠé¢æ°ã¯WHEREãGROUP BYãHAVINGã®åŸã«å®è¡ãããORDER BYãšLIMITã®åã«å®è¡ãããŸãããã®ãããWHEREå¥å ã§ãŠã£ã³ããŠé¢æ°ãçŽæ¥äœ¿çšããããšã¯ã§ããŸããããŠã£ã³ããŠé¢æ°ã®çµæã§ãã£ã«ã¿ãªã³ã°ããã«ã¯ãã¯ãšãªãCTEãŸãã¯ãµãã¯ãšãªã§ã©ããããŠãã ããã
åæã¯ãšãªã®ããã©ãŒãã³ã¹æé©å
ãŠã£ã³ããŠé¢æ°ãšCTEã¯åŒ·åãªããŒã«ã§ãããå€§èŠæš¡ãªããŒãã«ã§ã¯ããã«ããã¯ã«ãªãå¯èœæ§ããããŸããã¹ã±ãŒã©ãã«ãªããã©ãŒãã³ã¹ãç¶æããããã®ãã¯ããã¯ã玹ä»ããŸãã
第äžã«ãPARTITION BYããã³ORDER BYå¥ã§äœ¿çšãããåã«ã€ã³ããã¯ã¹ãäœæããŸãããŠã£ã³ããŠå®çŸ©ã«äžèŽããè€åã€ã³ããã¯ã¹ãããã°ããœãŒãæäœãçç¥ã§ããŸãã
第äºã«ããŠã£ã³ããŠé¢æ°ãé©çšããåã«ããŒã¿ããã£ã«ã¿ãªã³ã°ããŸããWHEREå¥ïŒãŠã£ã³ããŠé¢æ°ã®è©äŸ¡åã«å®è¡ãããïŒã«æ¡ä»¶ãé 眮ããããšã§ããŠã£ã³ããŠãåŠçããããŒã¿ã»ãããåæžã§ããŸãã
第äžã«ãåé·ãªãŠã£ã³ããŠå®çŸ©ãé¿ããŸããååä»ããŠã£ã³ããŠã䜿ãããšã§ç¹°ãè¿ããæžããããªããã£ãã€ã¶ã«å¯ŸããŠè€æ°ã®é¢æ°ãåããã¬ãŒã ãå ±æããŠããããšã瀺ãããšãã§ããŸãã
-- named_window.sql
SELECT
department,
employee_id,
salary,
RANK() OVER dept_window AS dept_rank,
SUM(salary) OVER dept_window AS dept_total,
AVG(salary) OVER dept_window AS dept_avg
FROM employees
WINDOW dept_window AS (
PARTITION BY department
ORDER BY salary DESC
);WINDOWå¥ïŒPostgreSQLãMySQL 8以éãBigQueryã§ãµããŒãïŒã¯ããŠã£ã³ããŠãäžåºŠå®çŸ©ããŠè€æ°ã®é¢æ°ã§åå©çšã§ããŸããå¯èªæ§ã®åäžãšã¯ãšãªãã©ã³æé©åã®äž¡æ¹ã«å¯äžããŸãã
Data Analyticsã®é¢æ¥å¯Ÿçã¯ã§ããŠããŸããïŒ
ã€ã³ã¿ã©ã¯ãã£ããªã·ãã¥ã¬ãŒã¿ãŒãflashcardsãæè¡ãã¹ãã§ç·Žç¿ããŸãããã
ãŸãšã
- ãŠã£ã³ããŠé¢æ°ïŒROW_NUMBERãRANKãDENSE_RANKãLAGãLEADãNTILEïŒã¯ãGROUP BYéçŽãšã¯ç°ãªããè¡ãéçŽããã«è¡ã®éåã«å¯ŸããŠèšç®ãå®è¡ããŸã
- CTEã¯è€éãªã¯ãšãªãååä»ãã®ãã¹ãå¯èœãªã¹ãããã«åè§£ããæ·±ããã¹ãããããµãã¯ãšãªã眮ãæããŸã
- ååž°CTEã¯çµç¹å³ãã«ããŽãªããªãŒãªã©ã®éå±€ããŒã¿ãåŠçããŸãããæ·±ãã®å¶éãšã€ã³ããã¯ã¹ä»ãçµååãå¿ èŠã§ã
- ã®ã£ãããšã¢ã€ã©ã³ããã¯ããã¯ïŒROW_NUMBERïŒæ¥ä»æŒç®ïŒã¯ãæç³»åããŒã¿ã®é£ç¶ã·ãŒã±ã³ã¹ãèå¥ããŸã
- ååä»ããŠã£ã³ããŠïŒWINDOWå¥ïŒã¯ã³ãŒãã®éè€ãæžãããã¯ãšãªãã©ã³ã®æé©åãæ¹åããå¯èœæ§ããããŸã
- WHEREå¥ã§ãŠã£ã³ããŠé¢æ°ã®è©äŸ¡åã«ããŒã¿ããã£ã«ã¿ãªã³ã°ããããšã§ãå€§èŠæš¡ããŒãã«ã§ã®ããã©ãŒãã³ã¹ãç¶æã§ããŸã
- ãããã®ãã¿ãŒã³ã¯ããŒã¿ã¢ããªã¹ã颿¥ã§é »åºã§ãããæ¥åžžã®ã¬ããŒãã£ã³ã°ãã»ã°ã¡ã³ããŒã·ã§ã³ããã¬ã³ãåæã«ãçŽæ¥å¿çšã§ããŸã
ä»ããç·Žç¿ãå§ããŸãããïŒ
颿¥ã·ãã¥ã¬ãŒã¿ãŒãšæè¡ãã¹ãã§ç¥èããã¹ãããŸãããã
Data Analytics ã®ãã°ãèŠã€ããããŸãã
å®éã®ã³ãŒããé ãããã°ã1æ¥1åãã¢ã«ãŠã³ããªãã§è©ŠããŸãã

å·ç
Anthony Fillion-MailletSharpSkill 嵿¥è
10 幎以äžãã«ã¹ã¿ãã¯éçºã«æºãã£ãŠããŸããSharpSkill ãéå¶ããããã§å ¬éãããå 容ã«è²¬ä»»ãè² ã£ãŠããŸãã
2026幎4æ9æ¥ æŽæ°
ã¿ã°
å ±æ
é¢é£èšäº

2026幎ã€ã¿ãªã¢ã®ããŒã¿ã¢ããªã¹ã颿¥è³ªå: SQLãPythonãåæã¹ãã«å®å šã¬ã€ã
ã€ã¿ãªã¢ã§2026幎ã«ããŒã¿ã¢ããªã¹ããšããŠæ¡çšãããããã®é¢æ¥å¯Ÿçã¬ã€ããSQLãPythonãpandasãããžãã¹åæã«é¢ããé »åºè³ªåãšæš¡ç¯è§£çã詳ãã解説ããŸãã

ããŒã¿ã¢ããªã¹ã颿¥å¯Ÿç2026幎çïŒSQLã»Pythonã»åæã¹ãã«å®å šã¬ã€ã
2026幎ã®ããŒã¿ã¢ããªã¹ã颿¥ã§é »åºããSQLãPythonãçµ±èšåæã®è³ªåãšæš¡ç¯è§£çã培åºè§£èª¬ãå®è·µçãªã³ãŒãäŸãšè§£çã®ãã€ã³ãã§å å®ç²åŸãç®æãã

2026幎ç ããŒã¿ã¢ããªã¹ãã®ããã®dbtå ¥éïŒã¢ããªã³ã°ããã¹ãã颿¥å¯Ÿç
dbtã®ãããžã§ã¯ãæ§é ããããªã¢ã©ã€ãŒãŒã·ã§ã³æŠç¥ãããŒã¿å質ãã¹ããJinjaãã¯ãããããŠ2026å¹Žã®æè¡é¢æ¥ã§ããåããã質åãç¶²çŸ çã«è§£èª¬ããŸãã