Aufgaben-Python/courses/sql/09_aggregate_und_group_by/musterloesung.sql

138 lines
4.4 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 09: MUSTERLÖSUNG – AGGREGATIONEN & GROUP BY 💡
-- ============================================================================
CREATE TABLE IF NOT EXISTS kunden (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
stadt TEXT NOT NULL,
status TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS kategorien (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS produkte (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
kategorie_id INTEGER NOT NULL,
preis REAL NOT NULL,
FOREIGN KEY (kategorie_id) REFERENCES kategorien(id)
);
CREATE TABLE IF NOT EXISTS bestellungen (
id INTEGER PRIMARY KEY,
kunde_id INTEGER NOT NULL,
bestell_datum TEXT NOT NULL,
status TEXT NOT NULL,
gesamtbetrag REAL NOT NULL,
FOREIGN KEY (kunde_id) REFERENCES kunden(id)
);
CREATE TABLE IF NOT EXISTS bestellpositionen (
id INTEGER PRIMARY KEY,
bestell_id INTEGER NOT NULL,
produkt_id INTEGER NOT NULL,
menge INTEGER NOT NULL,
einzelpreis REAL NOT NULL,
FOREIGN KEY (bestell_id) REFERENCES bestellungen(id),
FOREIGN KEY (produkt_id) REFERENCES produkte(id)
);
-- Testdaten einfügen
INSERT OR REPLACE INTO kunden (id, name, stadt, status) VALUES
(1, 'Alice Becker', 'Berlin', 'aktiv'),
(2, 'Bob Meier', 'Hamburg', 'aktiv'),
(3, 'Carla Wagner', 'München', 'aktiv'),
(4, 'David Fischer', 'Berlin', 'inaktiv'),
(5, 'Eva Klein', 'Hamburg', 'aktiv');
INSERT OR REPLACE INTO kategorien (id, name) VALUES
(1, 'Elektronik'),
(2, 'Bücher'),
(3, 'Kleidung');
INSERT OR REPLACE INTO produkte (id, name, kategorie_id, preis) VALUES
(101, 'Smartphone Pro', 1, 799.00),
(102, 'Kopfhörer Wireless', 1, 149.00),
(103, 'SQL Handbuch', 2, 49.90),
(104, 'Python Kochbuch', 2, 39.90),
(105, 'Outdoor Jacke', 3, 120.00),
(106, 'Laufschuhe', 3, 89.00);
INSERT OR REPLACE INTO bestellungen (id, kunde_id, bestell_datum, status, gesamtbetrag) VALUES
(1001, 1, '2024-01-15', 'abgeschlossen', 948.00),
(1002, 2, '2024-01-20', 'abgeschlossen', 149.00),
(1003, 1, '2024-02-10', 'abgeschlossen', 89.80),
(1004, 3, '2024-02-15', 'abgeschlossen', 799.00),
(1005, 4, '2024-03-01', 'storniert', 300.00),
(1006, 2, '2024-03-12', 'abgeschlossen', 450.00),
(1007, 5, '2024-03-25', 'abgeschlossen', 209.00);
INSERT OR REPLACE INTO bestellpositionen (id, bestell_id, produkt_id, menge, einzelpreis) VALUES
(1, 1001, 101, 1, 799.00),
(2, 1001, 102, 1, 149.00),
(3, 1002, 102, 1, 149.00),
(4, 1003, 103, 1, 49.90),
(5, 1003, 104, 1, 39.90),
(6, 1004, 101, 1, 799.00),
(7, 1006, 105, 3, 120.00),
(8, 1006, 106, 1, 89.00),
(9, 1007, 105, 1, 120.00),
(10, 1007, 106, 1, 89.00);
-- 🎯 TODO 1: Kategorie-Umsatz-Statistik
SELECT
k.name AS kategorie_name,
SUM(bp.menge) AS anzahl_verkaeufe,
SUM(bp.menge * bp.einzelpreis) AS gesamtumsatz,
ROUND(AVG(bp.einzelpreis), 2) AS avg_preis,
MIN(bp.einzelpreis) AS min_preis,
MAX(bp.einzelpreis) AS max_preis
FROM kategorien k
JOIN produkte p ON k.id = p.kategorie_id
JOIN bestellpositionen bp ON p.id = bp.produkt_id
GROUP BY k.id, k.name
ORDER BY gesamtumsatz DESC;
-- 🎯 TODO 2: Top-Kunden mit HAVING
SELECT
k.name,
k.stadt,
COUNT(b.id) AS bestell_anzahl,
SUM(b.gesamtbetrag) AS kunden_umsatz
FROM kunden k
JOIN bestellungen b ON k.id = b.kunde_id
WHERE b.status = 'abgeschlossen'
GROUP BY k.id, k.name, k.stadt
HAVING COUNT(b.id) >= 2 AND SUM(b.gesamtbetrag) >= 500.00
ORDER BY kunden_umsatz DESC;
-- 🎯 TODO 3: Monatlicher Umsatz- & KPI-Report
SELECT
strftime('%Y-%m', bestell_datum) AS monat,
COUNT(id) AS anzahl_bestellungen,
SUM(gesamtbetrag) AS monats_umsatz,
ROUND(AVG(gesamtbetrag), 2) AS avg_warenkorb
FROM bestellungen
WHERE status = 'abgeschlossen'
GROUP BY strftime('%Y-%m', bestell_datum)
ORDER BY monat ASC;
-- 🎯 TODO 4: Multi-Column GROUP BY (Städte & Kategorien)
SELECT
k.stadt,
kat.name AS kategorie_name,
COUNT(DISTINCT b.id) AS eindeutige_bestellungen,
SUM(bp.menge * bp.einzelpreis) AS umsatz_summe
FROM kunden k
JOIN bestellungen b ON k.id = b.kunde_id
JOIN bestellpositionen bp ON b.id = bp.bestell_id
JOIN produkte p ON bp.produkt_id = p.id
JOIN kategorien kat ON p.kategorie_id = kat.id
WHERE b.status = 'abgeschlossen'
GROUP BY k.stadt, kat.name
HAVING SUM(bp.menge * bp.einzelpreis) > 300
ORDER BY k.stadt ASC, umsatz_summe DESC;