Die Aktivitäten zu Datenbanken arbeiten mit drei Datensätzen aus offenen Quellen: den Ländern der Welt, Filmen und Musik. Hier steht für jeden, welche Tabellen und Spalten er hat, woher die Daten kommen, was drin ist und was nicht, und wie du ihn in deine Datenbank lädst.
Alle drei liegen im Repository specht/workspace-files, jeder in einem eigenen Ordner mit denselben Dateien, benannt nach dem Datensatz, etwa für die Länder: countries.sql mit Tabellen und Daten, countries-schema.sql nur mit den Tabellen, countries-data.sql nur mit den Daten (für Tabellen, die du selbst angelegt hast), dazu Teile der Daten zum schrittweisen Laden, countries-neo4j.dump für Neo4j und eine README.md. Gebaut werden sie von Skripten im Repository des Workspaces (src/scripts/collect-…), die man jederzeit neu laufen lassen kann; so bleiben die Zahlen aktuell.
Jede Tabelle steht in einer Zeile, ihre Spalten in Klammern:
Unterstrichen ist der Primärschlüssel, die Spalte oder die Spalten, deren Werte jede Zeile eindeutig machen. Mit ↑ beginnt ein Fremdschlüssel, eine Spalte, die auf eine Zeile einer anderen Tabelle verweist; worauf genau, zeigt ein Tooltip, wenn du mit der Maus darauf zeigst. In movie_genre sind beide Spalten zugleich Fremdschlüssel und zusammen der Primärschlüssel: Jedes Paar aus Film und Genre kommt nur einmal vor.
Alle 197 Länder der Welt mit ihren Kontinenten, gut 4.700 Städte, die Grenzen zwischen den Ländern, ihre Währungen und Amtssprachen. Es gibt sie in zwei Fassungen. Die kleine, countries-basic.sql, lädt die Einführung in SQL im ersten Teil, drei Tabellen für SELECT, WHERE und ORDER BY:
Die ganze, countries.sql, hat dazu die Grenzen, die Währungen und die Sprachen, und in country vier Spalten mehr: genug für JOIN, GROUP BY und eine Beziehung n:m, die der zweite Teil der Einführung behandelt. Sie ersetzt beim Import die drei Tabellen der kleinen; Länder, Städte und Kontinente bleiben dieselben.
| Spalte | Bedeutung |
|---|---|
continent.name, area
|
einer der sieben Kontinente auf Deutsch, von Afrika bis Südamerika, und seine Fläche in km² |
country.code |
das Kürzel aus drei Buchstaben nach ISO 3166 (DEU, FRA); Kosovo hat keines und bekommt XKS
|
country.population, area
|
die Einwohnerzahl, die letzte, die Wikidata kennt, und die Fläche in km² |
country.continent |
der Kontinent; ein Land auf zwei Kontinenten zählt dort, wo seine Hauptstadt liegt: Russland in Europa, die Türkei in Asien, Ägypten in Afrika |
country.currency_code |
die Währung mit ihrem Kürzel nach ISO 4217 (EUR, CHF); ihr Name steht in currency, und viele Länder teilen sich eine: den Euro 27 |
country.tld |
die Internet-Endung (.de, .uk); Kosovo hat keine eigene |
country.calling_code |
die Vorwahl mit + (+49); die Vereinigten Staaten und Kanada teilen sich die +1, die Inseln der Karibik haben drei Ziffern dahinter (+1268 für Antigua und Barbuda) |
country.driving_side |
left oder right: auf welcher Seite der Straße gefahren wird |
city.id |
eine Nummer, nach Land und Name vergeben; Namen gibt es mehrfach (Springfield dreimal in den Vereinigten Staaten) |
city.name |
der deutsche Name, wo es einen gibt (München, Mailand), sonst der englische |
city.population |
die Einwohner innerhalb der Stadtgrenzen, nicht des Ballungsraums; wo die Grenzen viel Land einschließen, wird die Zahl groß: Chongqing hat 30 Millionen |
city.latitude, longitude
|
Breite und Länge in Grad; Norden und Osten positiv, Süden und Westen negativ |
city.is_capital |
1 für die Hauptstadt, sonst 0; jedes Land hat genau eine |
border |
eine Landgrenze, in beide Richtungen: ('DEU', 'FRA') und ('FRA', 'DEU')
|
language.code, name
|
eine Sprache mit ihrem Kürzel nach ISO 639-3 (deu, fra, roh für Bündnerromanisch) und ihrem deutschen Namen |
country_language |
welche Sprache in welchem Land Amtssprache ist: die Schweiz hat vier, Englisch ist es in 59 Ländern |
Jede Grenze steht also zweimal da, mit Absicht. Einmal würde reichen, die Tabelle wäre dann frei von Wiederholungen, aber jede Frage nach den Nachbarn eines Landes müsste in beiden Spalten suchen. So genügt ein einfacher JOIN. Der Preis: Die Datenbank kann nicht verhindern, dass jemand nur eine Richtung einträgt und die beiden Hälften einander widersprechen.
Was drin ist. Die 193 Mitglieder der Vereinten Nationen, die beiden Beobachterstaaten Vatikanstadt und Palästina, Kosovo und Taiwan. Dänemark und die Niederlande ohne Grönland, die Färöer und die Karibikinseln. Als Stadt zählt jeder Ort ab 100.000 Einwohnern, dazu jede Hauptstadt, auch die kleinste: Ngerulmud, der Regierungssitz von Palau, hat gar keine Einwohner; Stadtteile, Ballungsräume und Landkreise zählen nicht. Die Zahlen stammen nicht alle aus demselben Jahr. Grenzen sind nur die an Land: 39 Länder, meist Inseln, haben keine Nachbarn. Überseegebiete zählen mit, so grenzt Frankreich über Französisch-Guayana an Brasilien. Eine Stadt, die Wikidata zwei Ländern zuordnet, gehört zu dem, dessen Hauptstadt näher liegt: Donezk und die Krim zur Ukraine, Prizren zum Kosovo. Jedes Land hat eine Währung, die es heute benutzt; wo Wikidata mehrere nennt, die eigene (Panama den Balboa neben dem US-Dollar). Amtssprachen zählen für das ganze Land, nicht für eine Region: Russland hat eine, nicht die Sprachen seiner Republiken.
Woher, und darf ich das? Alles stammt aus Wikidata und steht unter CC0. Wikidata schreiben viele Menschen; eine falsche Zahl verbessert man am besten dort, beim nächsten Bau ist sie dann richtig.
Laden. Die ganze Fassung; für die kleine steht countries-basic.sql statt countries.sql:
wget https://github.com/specht/workspace-files/raw/main/country-archive/countries.sql
mysql < countries.sql
Die Nachbarn eines Landes holt ein JOIN von border mit country:
SELECT neighbor.name FROM border JOIN country AS neighbor ON neighbor.code = border.neighbor_code WHERE border.country_code = 'DEU';
In Neo4j: Knoten Continent, Country, City, Currency und Language, (Country)-[:ON]->(Continent), (City)-[:IN]->(Country), (Country)-[:CAPITAL]->(City), (Country)-[:PAYS_WITH]->(Currency), (Country)-[:SPEAKS]->(Language) und (Country)-[:BORDERS]->(Country), einmal pro Paar.
Benutzt in: Einführung in SQL (die kleine Fassung), SQL: Gruppieren und Verbinden (die ganze), im Query Stepper (die ganze) und in den Beispielen des Handbuchs zu SQL.
Rund 2.700 bekannte Spielfilme, ihre Genres und die Menschen, die an ihnen mitgearbeitet haben. Die Filmdatenbank baut diese Tabellen erst selbst aus einem ER-Modell und lädt dann die Daten hinein.
| Spalte | Bedeutung |
|---|---|
movie.title |
der englische Titel; german_title der deutsche, original_title der Originaltitel, beide nur, wenn sie anders lauten |
movie.year, runtime
|
das Jahr der ersten Veröffentlichung, die Länge in Minuten |
genre.name |
eines von 20 Genres auf Englisch, etwa Sci-Fi oder Animation; ein Film kann mehrere haben oder keines |
crew.name, birth_year, death_year
|
eine Person, ihr Geburts- und Todesjahr; beide können fehlen |
job.title |
eine Tätigkeit: actor, director, writer, composer, producer, cinematographer oder editor
|
movie_crew |
wer bei welchem Film was gemacht hat; eine Person steht pro Film und Tätigkeit einmal da |
Was drin ist. Spielfilme, die in IMDb mindestens 100.000 Stimmen haben; nur ihre IMDb-Nummer wird dafür benutzt, alles andere kommt aus Wikidata. Von den Menschen stehen pro Film die zehn bekanntesten Schauspielerinnen und Schauspieler da (gemessen an der Zahl ihrer Wikipedia-Artikel) und wer Regie geführt, geschrieben, komponiert, produziert, die Kamera geführt oder geschnitten hat. Titel sind nicht eindeutig: Einen Film erkennst du an seiner id oder an Titel und Jahr.
Woher, und darf ich das? Wikidata steht unter CC0: Die Daten dürfen ohne Nachfrage kopiert, verändert und weitergegeben werden.
Laden. Die Filmdatenbank lädt die Daten in zwei Schritten, wie sie das Modell wachsen lässt:
wget https://github.com/specht/workspace-files/raw/main/movie-archive/movies-data-films.sql wget https://github.com/specht/workspace-files/raw/main/movie-archive/movies-data-crew.sql
Alles auf einmal, mit den Tabellen: movie-archive/movies.sql. In Neo4j: Knoten Movie, Person und Genre, (Movie)-[:IN_GENRE]->(Genre) und (Person)-[:ACTOR|DIRECTOR|…]->(Movie).
Benutzt in: Filmdatenbank mit MySQL, Filmdatenbank mit Neo4j und im Query Stepper (dort nur Regie und Schauspiel, Schauspielerinnen und Schauspieler ab fünf Filmen).
Rund 3.100 Alben von gut 1.000 Künstlerinnen, Künstlern und Bands, mit ihren Titeln, Genres und wer in welcher Band spielt.
| Spalte | Bedeutung |
|---|---|
artist.born, died
|
Geburts- und Todesjahr, aus dem Profil bei Discogs gelesen; leer bei Bands und wo das Profil nichts sagt |
album.id |
die Nummer des Albums bei Discogs (master release); discogs_release_id die Ausgabe, aus der Land und Titel stammen |
album.year, country
|
das Jahr des Albums und wo diese Ausgabe erschienen ist |
album.versions |
wie viele Ausgaben Discogs von dem Album kennt; gut zum Sortieren nach Bekanntheit |
track.number, duration
|
die Nummer auf dem Album, ab 1, und die Länge in Sekunden; die Länge kann fehlen |
album_genre |
ein Album kann mehrere Genres haben |
artist_part_of |
wer (member_id) in welcher Band (band_id) spielt oder gespielt hat; beide sind Zeilen von artist
|
Was drin ist. Alben von einer festen Liste von Künstlerinnen, Künstlern und Bands, jeweils die übliche Ausgabe; keine Sampler, inoffiziellen Ausgaben, Neuauflagen oder Live-Mitschnitte von Tourneen. Ein Album braucht ein Jahr, ein Genre und eine Titelliste.
Woher, und darf ich das? Aus den monatlichen Datenexporten von Discogs, die unter CC0 stehen.
Laden.
wget https://github.com/specht/workspace-files/raw/main/music-archive/music.sql
mysql < music.sql
In Neo4j: Knoten Artist, Album, Track und Genre, (Artist)-[:RELEASED]->(Album), (Album)-[:HAS_TRACK]->(Track), (Album)-[:IN_GENRE]->(Genre) und (Artist)-[:MEMBER_OF]->(Artist).
Noch benutzt ihn keine Aktivität; er eignet sich für eigene Aufgaben zu JOIN und GROUP BY oder als zweiter Datensatz für dieselben Abfragen wie bei den Filmen.