Aufgaben-Python/courses/sql/16_master_abschlussprojekt_data_warehouse/aufgabe.sql

161 lines
7.8 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- ============================================================================
-- 💎 SQL 16: MASTER-ABSCHLUSSPROJEKT – E-COMMERCE ANALYTICS DATA WAREHOUSE 💎
-- ============================================================================
-- In diesem Master-Projekt baust du ein produktionsreifes E-Commerce Data Warehouse:
-- 1. Sternschema DDL & Indizes (Fakten- und Dimensionstabellen)
-- 2. Kohortenanalyse (Cohort Retention Matrix mit CTEs)
-- 3. RFM-Kundensegmentierung mit NTILE Window Functions
-- 4. Executive Business Intelligence Dashboard View
-- ----------------------------------------------------------------------------
-- 1. TABELLEN-SCHEMA (STAR SCHEMA DDL) & TESTDATEN
-- ----------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS dim_customers (
customer_key INTEGER PRIMARY KEY,
customer_id TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
city TEXT NOT NULL,
country TEXT NOT NULL,
signup_date TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS dim_products (
product_key INTEGER PRIMARY KEY,
product_id TEXT UNIQUE NOT NULL,
product_name TEXT NOT NULL,
category TEXT NOT NULL,
unit_cost REAL NOT NULL,
unit_price REAL NOT NULL
);
CREATE TABLE IF NOT EXISTS dim_channels (
channel_key INTEGER PRIMARY KEY,
channel_name TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS fact_orders (
order_key INTEGER PRIMARY KEY,
order_id TEXT UNIQUE NOT NULL,
customer_key INTEGER NOT NULL,
channel_key INTEGER NOT NULL,
order_date TEXT NOT NULL,
total_amount REAL NOT NULL,
status TEXT NOT NULL,
FOREIGN KEY (customer_key) REFERENCES dim_customers(customer_key),
FOREIGN KEY (channel_key) REFERENCES dim_channels(channel_key)
);
CREATE TABLE IF NOT EXISTS fact_order_items (
item_key INTEGER PRIMARY KEY AUTOINCREMENT,
order_key INTEGER NOT NULL,
product_key INTEGER NOT NULL,
quantity INTEGER NOT NULL,
unit_price REAL NOT NULL,
line_total REAL NOT NULL,
FOREIGN KEY (order_key) REFERENCES fact_orders(order_key),
FOREIGN KEY (product_key) REFERENCES dim_products(product_key)
);
-- B-Tree Indizes für analytische Fact-Lookups
CREATE INDEX IF NOT EXISTS idx_fact_orders_customer ON fact_orders(customer_key);
CREATE INDEX IF NOT EXISTS idx_fact_orders_date ON fact_orders(order_date);
CREATE INDEX IF NOT EXISTS idx_fact_items_order ON fact_order_items(order_key);
-- Testdaten (Dimensionen)
INSERT INTO dim_customers (customer_key, customer_id, name, city, country, signup_date) VALUES
(1, 'CUST-001', 'Alice Becker', 'Berlin', 'Germany', '2024-01-05'),
(2, 'CUST-002', 'Bob Meier', 'Hamburg', 'Germany', '2024-01-12'),
(3, 'CUST-003', 'Carla Wagner', 'München', 'Germany', '2024-01-20'),
(4, 'CUST-004', 'David Fischer', 'Wien', 'Austria', '2024-02-02'),
(5, 'CUST-005', 'Eva Klein', 'Zürich', 'Switzerland', '2024-02-15'),
(6, 'CUST-006', 'Felix Wolf', 'Köln', 'Germany', '2024-03-01'),
(7, 'CUST-007', 'Grace Hopper', 'Berlin', 'Germany', '2024-03-10');
INSERT INTO dim_products (product_key, product_id, product_name, category, unit_cost, unit_price) VALUES
(1, 'PROD-01', 'Cloud Server S', 'Hosting', 20.00, 49.00),
(2, 'PROD-02', 'Cloud Server L', 'Hosting', 60.00, 149.00),
(3, 'PROD-03', 'Enterprise Database', 'Software', 150.00, 499.00),
(4, 'PROD-04', 'Security Suite Pro', 'Software', 50.00, 199.00),
(5, 'PROD-05', 'Consulting Tagessatz', 'Services', 400.00, 950.00);
INSERT INTO dim_channels (channel_key, channel_name) VALUES
(1, 'Web Direct'),
(2, 'Partner Referral'),
(3, 'Sales Outbound');
-- Testdaten (Fakten: Bestellungen über Jan, Feb, Mär, Apr 2024)
INSERT INTO fact_orders (order_key, order_id, customer_key, channel_key, order_date, total_amount, status) VALUES
(1001, 'ORD-1001', 1, 1, '2024-01-10', 49.00, 'COMPLETED'),
(1002, 'ORD-1002', 2, 2, '2024-01-15', 149.00, 'COMPLETED'),
(1003, 'ORD-1003', 3, 1, '2024-01-22', 499.00, 'COMPLETED'),
(1004, 'ORD-1004', 1, 1, '2024-02-05', 199.00, 'COMPLETED'),
(1005, 'ORD-1005', 2, 2, '2024-02-18', 149.00, 'COMPLETED'),
(1006, 'ORD-1006', 4, 3, '2024-02-20', 950.00, 'COMPLETED'),
(1007, 'ORD-1007', 5, 1, '2024-02-25', 49.00, 'COMPLETED'),
(1008, 'ORD-1008', 1, 1, '2024-03-02', 499.00, 'COMPLETED'),
(1009, 'ORD-1009', 3, 1, '2024-03-12', 49.00, 'COMPLETED'),
(1010, 'ORD-1010', 6, 2, '2024-03-15', 950.00, 'COMPLETED'),
(1011, 'ORD-1011', 7, 1, '2024-03-20', 149.00, 'COMPLETED'),
(1012, 'ORD-1012', 1, 1, '2024-04-05', 950.00, 'COMPLETED'),
(1013, 'ORD-1013', 2, 2, '2024-04-10', 149.00, 'COMPLETED'),
(1014, 'ORD-1014', 4, 3, '2024-04-15', 499.00, 'COMPLETED');
-- ============================================================================
-- 🎯 MASTER-AUFGABEN
-- ============================================================================
-- 🎯 TODO 1: Data Warehouse Health & KPI Basis Check
-- Schreibe eine Abfrage, die über Joins die Top 3 Produkte nach Gesamtumsatz liefert:
-- - product_name, category, anzahl_verkaeufe (COUNT), gesamt_umsatz (SUM(total_amount))
-- Sortiere nach gesamt_umsatz DESC und limitiere auf 3.
-- TODO: SELECT Query für Top-3 Produkte
-- 🎯 TODO 2: Kohorten-Retention-Matrix (Cohort Analysis)
-- Ermittle für jede Akquisitions-Kohorte (Monat des ersten Kaufs) das Wiederkaufverhalten:
-- Baue folgende CTE-Pipeline:
-- 1. `kunden_kohorte`: customer_key, kohorte (strftime('%Y-%m', MIN(order_date)))
-- 2. `kunden_aktivitaet`: customer_key, kohorte, aktivitaets_monat (strftime('%Y-%m', order_date))
-- 3. `kohorten_basis`: kohorte, kohorten_groesse (COUNT(DISTINCT customer_key))
-- 4. `retention_matrix`: kohorte, aktivitaets_monat, aktive_kunden (COUNT(DISTINCT customer_key)),
-- kohorten_groesse,
-- retention_rate_pct = ROUND(aktive_kunden * 100.0 / kohorten_groesse, 1)
-- Sortiere nach kohorte ASC, aktivitaets_monat ASC.
-- TODO: Multi-CTE Kohorten-Matrix schreiben
-- 🎯 TODO 3: RFM-Kundensegmentierung (Recency, Frequency, Monetary)
-- Segmentiere alle Kunden (customer_key, name) zum Stichtag '2024-04-30':
-- 1. `rfm_raw`:
-- - customer_key
-- - recency_tage: CAST(julianday('2024-04-30') - julianday(MAX(order_date)) AS INTEGER)
-- - frequency: COUNT(order_key)
-- - monetary: SUM(total_amount)
-- 2. `rfm_scored`:
-- - r_score: NTILE(4) OVER (ORDER BY recency_tage DESC) (kürzere Tage = höherer Score)
-- - f_score: NTILE(4) OVER (ORDER BY frequency ASC)
-- - m_score: NTILE(4) OVER (ORDER BY monetary ASC)
-- 3. Haupt-SELECT mit Segment-Zuweisung:
-- CASE
-- WHEN r_score >= 3 AND f_score >= 3 AND m_score >= 3 THEN 'Champions'
-- WHEN f_score >= 3 THEN 'Loyal Customers'
-- WHEN r_score <= 2 AND f_score >= 2 THEN 'At Risk'
-- ELSE 'Potential / Hibernating'
-- END AS kunden_segment
-- Sortiere nach monetary DESC.
-- TODO: RFM CTEs und Segmentierung schreiben
-- 🎯 TODO 4: Executive Business Intelligence View (v_executive_kpi_dashboard)
-- Erstelle einen View `v_executive_kpi_dashboard`, der monatliche Kennzahlen liefert:
-- - monat: strftime('%Y-%m', order_date)
-- - monats_umsatz: SUM(total_amount)
-- - anzahl_bestellungen: COUNT(order_key)
-- - aktive_kunden: COUNT(DISTINCT customer_key)
-- - aov: ROUND(AVG(total_amount), 2) (Average Order Value)
-- - vormonat_umsatz: LAG(SUM(total_amount), 1, 0) OVER (ORDER BY strftime('%Y-%m', order_date))
-- - mom_wachstum_pct: ROUND((SUM(total_amount) - LAG(SUM(total_amount), 1, SUM(total_amount)) OVER (ORDER BY strftime('%Y-%m', order_date))) * 100.0 / LAG(SUM(total_amount), 1, SUM(total_amount)) OVER (ORDER BY strftime('%Y-%m', order_date)), 2)
-- - kumulierter_allzeit_umsatz: SUM(SUM(total_amount)) OVER (ORDER BY strftime('%Y-%m', order_date) ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
-- Gruppiere im View nach strftime('%Y-%m', order_date).
-- TODO: CREATE VIEW v_executive_kpi_dashboard AS ...