PMG2426 1/DB Beleg/Tim

Aus ProgrammingWiki

Wiki-Quelltext dieser Seite.

<language>SQL</language>
<html><h3>Relationenmodell</h3></html>
[[Bild:Timi_Screenshot_(21).png|1050px|center]]
<html><h3>ER-Modell</h3></html>
[[Bild:Timi_Erdplus_(2).png|1050px|center]]
<code id="69825bec9a29a">DROP TABLE IF EXISTS RENNERGEBNIS;
DROP TABLE IF EXISTS FAHRER_TEAM;
DROP TABLE IF EXISTS RENNEN;
DROP TABLE IF EXISTS STRECKE;
DROP TABLE IF EXISTS FAHRER;
DROP TABLE IF EXISTS TEAM;

CREATE TABLE TEAM (
Team_ID INT PRIMARY KEY,
Teamname VARCHAR(100),
Hauptsitz VARCHAR(100),
Teamchef VARCHAR(100),
Motor VARCHAR(50)
);

CREATE TABLE FAHRER (
Fahrer_ID INT PRIMARY KEY,
Vorname VARCHAR(50),
Nachname VARCHAR(50),
Startnummer INT,
Nationalitaet VARCHAR(50),
Geburtsdatum DATE
);

CREATE TABLE STRECKE (
Strecken_ID INT PRIMARY KEY,
Streckenname VARCHAR(100),
Land VARCHAR(50),
Streckenlaenge_km DECIMAL(5,3),
Rundenanzahl INT
);

CREATE TABLE RENNEN (
Rennen_ID INT PRIMARY KEY,
Rennenname VARCHAR(100),
Datum DATE,
Saison INT,
Strecken_ID INT,
FOREIGN KEY (Strecken_ID) REFERENCES STRECKE(Strecken_ID)
);

CREATE TABLE FAHRER_TEAM (
Fahrer_ID INT,
Team_ID INT,
Von_Datum DATE,
Bis_Datum DATE,
PRIMARY KEY (Fahrer_ID, Team_ID, Von_Datum),
FOREIGN KEY (Fahrer_ID) REFERENCES FAHRER(Fahrer_ID),
FOREIGN KEY (Team_ID) REFERENCES TEAM(Team_ID)
);

CREATE TABLE RENNERGEBNIS (
Ergebnis_ID INT PRIMARY KEY,
Rennen_ID INT,
Fahrer_ID INT,
Platzierung INT,
Punkte INT,
Rennzeit VARCHAR(10),
Status VARCHAR(20),
FOREIGN KEY (Rennen_ID) REFERENCES RENNEN(Rennen_ID),
FOREIGN KEY (Fahrer_ID) REFERENCES FAHRER(Fahrer_ID)
);

INSERT INTO TEAM VALUES (1, 'Red Bull Racing', 'Milton Keynes', 'Christian Horner', 'Honda RBPT');
INSERT INTO TEAM VALUES (2, 'Ferrari', 'Maranello', 'Frederic Vasseur', 'Ferrari');
INSERT INTO TEAM VALUES (3, 'Mercedes', 'Brackley', 'Toto Wolff', 'Mercedes');
INSERT INTO TEAM VALUES (4, 'McLaren', 'Woking', 'Andrea Stella', 'Mercedes');
INSERT INTO TEAM VALUES (5, 'Aston Martin', 'Silverstone', 'Mike Krack', 'Mercedes');
INSERT INTO TEAM VALUES (6, 'Alpine', 'Enstone', 'Oliver Oakes', 'Renault');
INSERT INTO TEAM VALUES (7, 'Williams Racing', 'Grove', 'James Vowles', 'Mercedes');
INSERT INTO TEAM VALUES (8, 'Racing Bulls', 'Faenza', 'Laurent Mekies', 'Honda RBPT');
INSERT INTO TEAM VALUES (9, 'Haas F1 Team', 'Kannapolis', 'Ayao Komatsu', 'Ferrari');
INSERT INTO TEAM VALUES (10, 'Kick Sauber', 'Hinwil', 'Alessandro Alunni Bravi', 'Ferrari');

INSERT INTO FAHRER VALUES (1, 'Lando', 'Norris', 4, 'Grossbritannien', '1999-11-13');
INSERT INTO FAHRER VALUES (2, 'Max', 'Verstappen', 1, 'Niederlande', '1997-09-30');
INSERT INTO FAHRER VALUES (3, 'Oscar', 'Piastri', 81, 'Australien', '2001-04-06');
INSERT INTO FAHRER VALUES (4, 'George', 'Russell', 63, 'Grossbritannien', '1998-02-15');
INSERT INTO FAHRER VALUES (5, 'Charles', 'Leclerc', 16, 'Monaco', '1997-10-16');
INSERT INTO FAHRER VALUES (6, 'Lewis', 'Hamilton', 44, 'Grossbritannien', '1985-01-07');
INSERT INTO FAHRER VALUES (7, 'Kimi', 'Antonelli', 12, 'Italien', '2006-08-25');
INSERT INTO FAHRER VALUES (8, 'Alexander', 'Albon', 23, 'Thailand', '1996-03-23');
INSERT INTO FAHRER VALUES (9, 'Carlos', 'Sainz', 55, 'Spanien', '1994-09-01');
INSERT INTO FAHRER VALUES (10, 'Fernando', 'Alonso', 14, 'Spanien', '1981-07-29');
INSERT INTO FAHRER VALUES (11, 'Nico', 'Hulkenberg', 27, 'Deutschland', '1987-08-19');
INSERT INTO FAHRER VALUES (12, 'Isack', 'Hadjar', 6, 'Frankreich', '2004-09-28');
INSERT INTO FAHRER VALUES (13, 'Oliver', 'Bearman', 87, 'Grossbritannien', '2005-05-08');
INSERT INTO FAHRER VALUES (14, 'Liam', 'Lawson', 30, 'Neuseeland', '2002-02-11');
INSERT INTO FAHRER VALUES (15, 'Esteban', 'Ocon', 31, 'Frankreich', '1996-09-17');
INSERT INTO FAHRER VALUES (16, 'Lance', 'Stroll', 18, 'Kanada', '1998-10-29');
INSERT INTO FAHRER VALUES (17, 'Yuki', 'Tsunoda', 22, 'Japan', '2000-05-11');
INSERT INTO FAHRER VALUES (18, 'Pierre', 'Gasly', 10, 'Frankreich', '1996-02-07');
INSERT INTO FAHRER VALUES (19, 'Gabriel', 'Bortoleto', 5, 'Brasilien', '2004-10-14');
INSERT INTO FAHRER VALUES (20, 'Franco', 'Colapinto', 43, 'Argentinien', '2003-05-27');

INSERT INTO STRECKE VALUES (1, 'Albert Park Circuit', 'Australien', 5.278, 58);
INSERT INTO STRECKE VALUES (24, 'Yas Marina Circuit', 'Abu Dhabi', 5.281, 58);

INSERT INTO RENNEN VALUES (1, 'Saison 2025 Gesamt', '2025-12-07', 2025, 24);

INSERT INTO FAHRER_TEAM VALUES (1, 4, '2025-01-01', NULL);
INSERT INTO FAHRER_TEAM VALUES (2, 1, '2025-01-01', NULL);
INSERT INTO FAHRER_TEAM VALUES (3, 4, '2025-01-01', NULL);
INSERT INTO FAHRER_TEAM VALUES (4, 3, '2025-01-01', NULL);
INSERT INTO FAHRER_TEAM VALUES (5, 2, '2025-01-01', NULL);
INSERT INTO FAHRER_TEAM VALUES (6, 2, '2025-01-01', NULL);
INSERT INTO FAHRER_TEAM VALUES (7, 3, '2025-01-01', NULL);
INSERT INTO FAHRER_TEAM VALUES (8, 7, '2025-01-01', NULL);
INSERT INTO FAHRER_TEAM VALUES (9, 7, '2025-01-01', NULL);
INSERT INTO FAHRER_TEAM VALUES (10, 5, '2025-01-01', NULL);
INSERT INTO FAHRER_TEAM VALUES (11, 10, '2025-01-01', NULL);
INSERT INTO FAHRER_TEAM VALUES (12, 8, '2025-01-01', NULL);
INSERT INTO FAHRER_TEAM VALUES (13, 9, '2025-01-01', NULL);
INSERT INTO FAHRER_TEAM VALUES (14, 8, '2025-01-01', NULL);
INSERT INTO FAHRER_TEAM VALUES (15, 9, '2025-01-01', NULL);
INSERT INTO FAHRER_TEAM VALUES (16, 5, '2025-01-01', NULL);
INSERT INTO FAHRER_TEAM VALUES (17, 1, '2025-01-01', NULL);
INSERT INTO FAHRER_TEAM VALUES (18, 6, '2025-01-01', NULL);
INSERT INTO FAHRER_TEAM VALUES (19, 10, '2025-01-01', NULL);
INSERT INTO FAHRER_TEAM VALUES (20, 6, '2025-01-01', NULL);

INSERT INTO RENNERGEBNIS VALUES (1, 1, 1, 1, 423, NULL, 'Finished');
INSERT INTO RENNERGEBNIS VALUES (2, 1, 2, 2, 421, NULL, 'Finished');
INSERT INTO RENNERGEBNIS VALUES (3, 1, 3, 3, 410, NULL, 'Finished');
INSERT INTO RENNERGEBNIS VALUES (4, 1, 4, 4, 319, NULL, 'Finished');
INSERT INTO RENNERGEBNIS VALUES (5, 1, 5, 5, 242, NULL, 'Finished');
INSERT INTO RENNERGEBNIS VALUES (6, 1, 6, 6, 156, NULL, 'Finished');
INSERT INTO RENNERGEBNIS VALUES (7, 1, 7, 7, 150, NULL, 'Finished');
INSERT INTO RENNERGEBNIS VALUES (8, 1, 8, 8, 73, NULL, 'Finished');
INSERT INTO RENNERGEBNIS VALUES (9, 1, 9, 9, 64, NULL, 'Finished');
INSERT INTO RENNERGEBNIS VALUES (10, 1, 10, 10, 56, NULL, 'Finished');
INSERT INTO RENNERGEBNIS VALUES (11, 1, 11, 11, 51, NULL, 'Finished');
INSERT INTO RENNERGEBNIS VALUES (12, 1, 12, 12, 51, NULL, 'Finished');
INSERT INTO RENNERGEBNIS VALUES (13, 1, 13, 13, 41, NULL, 'Finished');
INSERT INTO RENNERGEBNIS VALUES (14, 1, 14, 14, 38, NULL, 'Finished');
INSERT INTO RENNERGEBNIS VALUES (15, 1, 15, 15, 38, NULL, 'Finished');
INSERT INTO RENNERGEBNIS VALUES (16, 1, 16, 16, 33, NULL, 'Finished');
INSERT INTO RENNERGEBNIS VALUES (17, 1, 17, 17, 33, NULL, 'Finished');
INSERT INTO RENNERGEBNIS VALUES (18, 1, 18, 18, 22, NULL, 'Finished');
INSERT INTO RENNERGEBNIS VALUES (19, 1, 19, 19, 19, NULL, 'Finished');
INSERT INTO RENNERGEBNIS VALUES (20, 1, 20, 20, 0, NULL, 'Finished');

SELECT Vorname, Nachname 
FROM FAHRER 
WHERE Nationalitaet = 'Grossbritannien';

SELECT f.Nachname, SUM(e.Punkte) as SaisonPunkte
FROM FAHRER f
JOIN RENNERGEBNIS e ON f.Fahrer_ID = e.Fahrer_ID
GROUP BY f.Nachname
ORDER BY SaisonPunkte DESC;</code>
<run id="69825bec9a331">SELECT * FROM FAHRER;</run>
<run id="6983174d2cb2b">SELECT Vorname, Nachname, Startnummer 
FROM FAHRER 
WHERE Nationalitaet = 'Grossbritannien'
ORDER BY Nachname;</run>

<run id="6983174d2cbb8">SELECT F.Vorname, F.Nachname, F.Startnummer, T.Teamname
FROM FAHRER F
JOIN FAHRER_TEAM FT ON F.Fahrer_ID = FT.Fahrer_ID
JOIN TEAM T ON FT.Team_ID = T.Team_ID
WHERE FT.Bis_Datum IS NULL
ORDER BY T.Teamname, F.Nachname;</run>

<run id="6983174d2cc37">SELECT 
    R.Rennenname, 
    R.Datum,
    F.Vorname, 
    F.Nachname, 
    T.Teamname
FROM RENNERGEBNIS RE
JOIN RENNEN R ON RE.Rennen_ID = R.Rennen_ID
JOIN FAHRER F ON RE.Fahrer_ID = F.Fahrer_ID
JOIN FAHRER_TEAM FT ON F.Fahrer_ID = FT.Fahrer_ID
JOIN TEAM T ON FT.Team_ID = T.Team_ID
WHERE RE.Platzierung = 1 
  AND FT.Bis_Datum IS NULL
ORDER BY R.Datum;</run>

<run id="6983174d2ccaa">SELECT 
    F.Vorname, 
    F.Nachname, 
    T.Teamname,
    SUM(RE.Punkte) AS Gesamt_Punkte
FROM FAHRER F
JOIN RENNERGEBNIS RE ON F.Fahrer_ID = RE.Fahrer_ID
JOIN FAHRER_TEAM FT ON F.Fahrer_ID = FT.Fahrer_ID
JOIN TEAM T ON FT.Team_ID = T.Team_ID
WHERE FT.Bis_Datum IS NULL
GROUP BY F.Fahrer_ID, F.Vorname, F.Nachname, T.Teamname
ORDER BY Gesamt_Punkte DESC;</run>

<run id="6983174d2cd1d">SELECT 
    T.Teamname,
    T.Motor,
    COUNT(DISTINCT R.Rennen_ID) AS Anzahl_Rennen,
    SUM(RE.Punkte) AS Gesamt_Punkte,
    ROUND(AVG(Punkte_Pro_Rennen), 2) AS Durchschnitt_Punkte_Pro_Rennen,
    MAX(Punkte_Pro_Rennen) AS Beste_Einzel_Performance
FROM TEAM T
JOIN FAHRER_TEAM FT ON T.Team_ID = FT.Team_ID
JOIN RENNERGEBNIS RE ON FT.Fahrer_ID = RE.Fahrer_ID
JOIN RENNEN R ON RE.Rennen_ID = R.Rennen_ID
JOIN (
    SELECT 
        FT2.Team_ID,
        RE2.Rennen_ID,
        SUM(RE2.Punkte) AS Punkte_Pro_Rennen
    FROM FAHRER_TEAM FT2
    JOIN RENNERGEBNIS RE2 ON FT2.Fahrer_ID = RE2.Fahrer_ID
    WHERE FT2.Bis_Datum IS NULL
    GROUP BY FT2.Team_ID, RE2.Rennen_ID
) AS Team_Rennen_Punkte 
ON T.Team_ID = Team_Rennen_Punkte.Team_ID
WHERE FT.Bis_Datum IS NULL
GROUP BY T.Team_ID, T.Teamname, T.Motor
ORDER BY Gesamt_Punkte DESC;</run>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; margin: 20px auto; }
h1 { border-bottom: 2px solid #e10600; }
h3 { margin-top: 25px; text-decoration: underline #e10600;}
ul { margin-bottom: 15px; }
{ text-align: center; margin: 20px 0; border: 1px solid #ddd padding: 10px; }
</style>
</head>

<body>

<h3>1. Zielstellung</h3>
<p>
Ziel ist die Erstellung einer relationalen Datenbank zur Verwaltung der Formel-1-Weltmeisterschaft 2025. Anstatt Rennergebnisse in unübersichtlichen Tabellenkalkulationen zu führen, ermöglicht diese Datenbank automatisierte Auswertungen (z.B. Punktestände, Team-Zugehörigkeiten) und verhindert Redundanzen bei der Dateneingabe. Die Datenbank verwaltet zentral alle relevanten Informationen der Saison – 20 Fahrer, 10 Teams und 24 Rennen auf verschiedenen Strecken weltweit – und stellt durch Normalisierung bis zur 3. Normalform sicher, dass jede Information nur einmal gespeichert wird. Durch referenzielle Integrität können Rennergebnisse nur für existierende Fahrer und Rennen eingetragen werden, was Inkonsistenzen verhindert. Komplexe Auswertungen wie die Fahrer-Weltmeisterschaft (Summierung aller Rennergebnisse), die Konstrukteurs-WM (Addition der Fahrerpunkte pro Team) oder Statistiken zu Siegen, Podiumsplätzen und Ausfällen lassen sich durch SQL-Abfragen in Sekundenbruchteilen generieren, während in Tabellenkalkulationen manuelle Formeln und Aktualisierungen nötig wären. Die Struktur ist flexibel erweiterbar für Team-Wechsel während der Saison (durch Von_Datum/Bis_Datum), zusätzliche Tabellen (z.B. für Qualifying-Ergebnisse) oder zukünftige Saisons und bietet praktischen Nutzen für Teams (Performance-Analysen), Journalisten (Statistiken für Berichterstattung), Fans (detaillierte historische Vergleiche) und Organisatoren (fehlerfreie WM-Verwaltung).

</p>


<h3>2. Modellierung & Reflexion</h3>

<p>
Die Modellierung und Umsetzung der Formel‑1‑Datenbank verlief weitgehend erfolgreich. Durch die klare Struktur mit sechs zentralen Tabellen – TEAM, FAHRER, STRECKE, RENNEN, FAHRER_TEAM und RENNERGEBNIS – entstand ein konsistentes Modell mit logisch nachvollziehbaren Beziehungen. Besonders hilfreich war die konsequente Nutzung von Primär‑ und Fremdschlüsseln, die eine saubere referenzielle Integrität sicherstellten. Auch die ER‑Modellierung sorgte dafür, dass Zusammenhänge zwischen Fahrern, Teams und Rennen frühzeitig klar waren und sich problemlos in SQL übertragen ließen.

Herausfordernd war die Modellierung der n:m‑Beziehung zwischen Fahrern und Teams. Diese konnte erst durch die Zwischentabelle FAHRER_TEAM korrekt umgesetzt werden, insbesondere um zeitliche Teamwechsel mit Von_Datum und Bis_Datum abzubilden. Der Umgang mit NULL‑Werten für aktive Fahrer‑Team‑Beziehungen erforderte genaue Abfragebedingungen, um aktuelle Daten korrekt zu filtern.

Insgesamt funktionierte die SQL‑Implementierung sehr zuverlässig. Die Testabfragen – etwa zur Fahrerwertung oder zur Ermittlung nationaler Zugehörigkeiten – bestätigten die Funktionsfähigkeit des Modells. Künftig könnten jedoch weitere Tabellen, wie für Qualifying‑Ergebnisse oder Strafen, die Datenbank erweitern und realitätsnäher gestalten. Das Projekt verdeutlichte die Bedeutung sorgfältiger Planung und zeigte, wie durchdachtes Design zu einer stabilen und flexiblen Datenstruktur führt.
</p>

<h4>Kardinalitäten</h4>
<ul>
<li><strong>1:n (Strecke zu Rennen):</strong> Eine Strecke richtet Rennen aus, aber ein Rennen findet auf genau einer Strecke statt.</li>
<li><strong>n:m (Fahrer zu Team):</strong> Ein Fahrer kann das Team wechseln. Diese Beziehung wird über die Tabelle <i>FAHRER_TEAM</i> aufgelöst.</li>
</ul>

<h3>3. Verwendete Quellen</h3>
<ul>
<li><a href="https://www.formula1.com">Formula1.com (Offizielle Daten)</a></li>
<li><a href="https://de.wikipedia.org/wiki/Formel-1-Weltmeisterschaft_2025">Wikipedia (Saison 2025)</a></li>
</ul>

</body>
</html>
[[Bild:Timi_Sidstappen-wallpaper-v0-2jv5sle2g50e1.png|1200px|center]]