docs/document-structure (#578)
Habe per toctree die verschiedenen Dokumente in die richtige Reihenfolge gebracht. --------- Co-authored-by: Tim Ronneburg <Tim-Ronneburg@users.noreply.github.com> Co-authored-by: Sebastian <94404394+SeZett@users.noreply.github.com> Co-authored-by: Philipp Horstenkamp <philipp@horstenkamp.de> Co-authored-by: SeZett <zeleny.sebastian@fh-swf.de>
@ -1,979 +0,0 @@
|
||||

|
||||
|
||||
<div style="page-break-after: always;"></div>
|
||||
|
||||
# Datenspeicherung
|
||||
|
||||
## Inhaltsverzeichnis
|
||||
|
||||
- [Datenspeicherung](#datenspeicherung)
|
||||
- [Inhaltsverzeichnis](#inhaltsverzeichnis)
|
||||
- [Motivation: Warum speichern wird Daten?](#motivation-warum-speichern-wird-daten)
|
||||
- [1. Allgemeine Anforderungen an Datenbank](#1-allgemeine-anforderungen-an-datenbank)
|
||||
- [2. Datenarten](#2-datenarten)
|
||||
- [2.1 Welche Daten erwarten wir im Projekt?](#21-welche-daten-erwarten-wir-im-projekt)
|
||||
- [2.2 strukturierte Daten](#22-strukturierte-daten)
|
||||
- [2.3 unstrukturierte Daten](#23-unstrukturierte-daten)
|
||||
- [3. Arten von Datenbanken](#3-arten-von-datenbanken)
|
||||
- [3.1 Relationale Datenbank](#31-relationale-datenbank)
|
||||
- [3.1.1 Anlegen von Tabellen](#311-anlegen-von-tabellen)
|
||||
- [3.1.2 SQL - Abfrage von relationalen Datenbanken](#312-sql---abfrage-von-relationalen-datenbanken)
|
||||
- [3.2 Graphdatenbank](#32-graphdatenbank)
|
||||
- [3.2.1 Erstellung eines Datensatzes](#321-erstellung-eines-datensatzes)
|
||||
- [3.2.2 Cypher - Abfrage von Graphdatenbanken](#322-cypher---abfrage-von-graphdatenbanken)
|
||||
- [3.3 Zeitseriendatenbank](#33-zeitseriendatenbank)
|
||||
- [3.3.1 Erstellung eines Datensatzes](#331-erstellung-eines-datensatzes)
|
||||
- [3.3.2 FluxQuery](#332-fluxquery)
|
||||
- [3.4 Dokumenten Datenbank ](#34-dokumenten-datenbank-)
|
||||
- [3.4.1 Erstellen einer Collection / Ablegen von Dokumenten](#341-erstellen-einer-collection--ablegen-von-dokumenten)
|
||||
- [3.5 Aufbau einer Datenbank](#35-aufbau-einer-datenbank)
|
||||
- [4. Datenbanken Transparenzregister](#4-datenbanken-transparenzregister)
|
||||
- [4.1 Production DB - relationales Datenbankmodell](#41-production-db---relationales-datenbankmodell)
|
||||
- [4.2 Staging DB](#42-staging-db)
|
||||
- [4.3 SQL Alchemy](#43-sql-alchemy)
|
||||
- [5. Proof of Concept](#5-proof-of-concept)
|
||||
- [5.1 Docker](#51-docker)
|
||||
- [5.2 PG Admin](#52-pg-admin)
|
||||
- [5.3 Erstellen von Mock Daten](#53-erstellen-von-mock-daten)
|
||||
- [5.4 Anlegen der relationalen Tabellen](#54-anlegen-der-relationalen-tabellen)
|
||||
- [5.5 Abfragen der Datenbank](#55-abfragen-der-datenbank)
|
||||
- [6. Zusammenfassung](#6-zusammenfassung)
|
||||
- [Quellen](#quellen)
|
||||
|
||||
<div style="page-break-after: always;"></div>
|
||||
|
||||
## Motivation: Warum speichern wird Daten?
|
||||
|
||||
Für die Speicherung von Daten gibt es verschiedene Motivationen:
|
||||
|
||||
- **Sammlung:** Zur Aufbewahrung von Wissen und Informationen über Objekte, Ereignisse oder Prozesse werden Daten
|
||||
gespeichert.
|
||||
- **Historisierung:** Durch die Speicherung von Daten in einem zeitlichen Zusammenhang, wird eine Historie erstellt, mit
|
||||
welcher Muster, Trends oder Zusammenhänge erkannt werden können. Historische Daten helfen ausserdem bei der
|
||||
Entscheidungsfindung.
|
||||
- **Bewertung:** Mit gespeicherten Daten können Systeme, Produkte und Prozesse nachvollzogen, bewertet und verbessert
|
||||
werden.
|
||||
|
||||
Im Projekt Transparenzregister ist die Datenspeicherung eine Kernkomponente, da die gesammelten Informationen die
|
||||
Grundlage für Analysen darstellen. \
|
||||
Mit geeigneten Pipelines werden aus diesen Daten Erkenntnisse extrahiert, um z.B. Verflechtungen zwischen Personen und
|
||||
Unternehmen oder den wirtschaftlichen Trend eines Unternehmens visualisieren und bewerten zu können.
|
||||
|
||||
## 1. Allgemeine Anforderungen an Datenbank
|
||||
|
||||
- **1.1 Speicherung/Integrität**: Das verwendete System muss Daten, wie Unternehmenskennzahlen, Stammdaten und
|
||||
Verflechtungen speichern. Die Daten müssen korrekt und konsistent gespeichert werden. Konsistent bedeutet in einem
|
||||
gültigen und widerspruchsfreien Zustand und die Transaktionen sollen den ACID-Eigenschaften entsprechen.
|
||||
- **Atomarity:** Eine Transaktion wird atomar betrachte, d.h. es ist die kleinste unteilbare Einheit, wodurch eine
|
||||
Transaktion entweder vollständig durchgeführt und übernommen wird (Commit) oder bei einem Fehler rückgängig
|
||||
gemacht
|
||||
wird (Rollback).
|
||||
- **Consistency:** Konsistenz bedeutet, dass eine Transaktion den Datenbankzustand von einem gültigen in einen
|
||||
anderen
|
||||
gültihgen Zustand überführt. Sollte eine Transaktion eine Konsitenzverletzung verursachen, wird diese abgebrochen
|
||||
und die Änderungen zurückgesetzt.
|
||||
- **Isolation:** Isolation sorgt dafür, dass alle Transaktion unabhängig voneinander ausgeführt werden, damit sich
|
||||
diese bei der Ausführung nicht gegenseitig beeinflussen.
|
||||
- **Durability:** Dauerhaftigkeit bedeutet, dass die Ergebnisse einer Transaktion dauerhaft in der Datenbank
|
||||
gespeichert werden und auch nach einem Systemneustart oder Systemfehler erhalten bleiben.
|
||||
- **1.2 Skalierbarkeit:** Das System soll skalierbar sein, um zukünftige Daten weiterhin zu speichern und weitere
|
||||
Unternehmen hinzuzufügen. Durch Hinzufügen von Ressourcen kann das System an steigende Datenmengen und
|
||||
Benutzeranforderungen angepasst werden. Man spricht von horizontaler Skalierung, da die Last auf mehrere
|
||||
Datenbankserver verteilt wird.
|
||||
- **1.3 Sicherheit:** Die Datenbank muss Mechanismen bereitstellen, um die Daten vor unbefugtem Zugriff zu schützen.
|
||||
- **Authentifizierung:** Überprüfung der Identität eines Benutzers, durch Benutzername und Passwort. Meist wird eine
|
||||
Zwei-Faktor-Authentifizierung verwendet, um das Sicherheitslevel zu erhöhen.
|
||||
- **Autorisierung:** Der authentifizierte Benutzer erhält bei der Autorisierung Zugriffsrechte und Ressourcen,
|
||||
welche
|
||||
auf seiner Benutzerrolle basieren. Ein Benutzer mit Administratorrechten, erhält Zugriff auf alle
|
||||
Systemressourcen,
|
||||
wohingegen ein normaler Benutzer nur beschränkten Zugriff erhält.
|
||||
- **Verschlüsselung:** Durch Verschlüsselung werden Daten in ein nicht interpretierbaren Code umgewandelt, um den
|
||||
Inhalt vor unbefugtem Zugriff zu schützen. Dafür wird ein Algorithmus verwendet, welcher einen Schlüssel generiert
|
||||
und die Daten mit diesem verschlüsselt. Um die Daten wieder lesen zu können, müssen diese mit dem Schlüssel
|
||||
dechiffriert werden.
|
||||
- **1.4 Datensicherung- und Wiederherstellung:** Die Datenbank muss Funktionen zur Sicherung und Wiederherstellung
|
||||
unterstützen. Im Falle eines Ausfalls oder Fehlers muss sichergestellt sein, dass Mechanismen die Daten schützen und
|
||||
wiederherstellen.
|
||||
Die meisten Daten in einer Datenbank ändern sich nur langsam, manche allerdings schnell. Je nach Anwendungsfall muss
|
||||
eine geeignete Sicherungsstrategie ausgewählt werden, um nur die Daten zu sichern, die sich tatsächlich ändern.
|
||||
Jedes Datenbankmanagementsystem bietet unterschiedliche Mechanismen zur Datensicherung und Wiederherstellung, dessen
|
||||
Möglichkeiten nach Auswahl eines Systems
|
||||
- **vollständiges Backup:** Das vollständige Backup ist eine komplette Kopie der Datenbank inkl. aller Daten,
|
||||
Indizes,
|
||||
Tabellen und Metadaten. Es benötigt viel Speicherplatz und Zeit zur Erzeugung der Sicherung und auch zur
|
||||
Wiederherstellung.
|
||||
- **inkrementelles Backup:** Ein inkrementelles Backup sichert nur die Änderungen seit dem letzten vollständigem
|
||||
bzw.
|
||||
inkrementellen Backup. Durch den verringerten Datenbestand ist es deutlich schneller und datensparsamer, als das
|
||||
vollständige Backup. Zur Wiederherstellung wird das letzte vollständige und alle inkrementellen Backups benötigt.
|
||||
Allerdings entsteht eine Abhängigkeitskette, da jedes Backup seine Vorgänger zur Wiederherstellung benötigt.
|
||||
- **differentielles Backup:** Beim differentiellen Backup werden alle Änderungen seit dem letzten vollständigem
|
||||
Backup
|
||||
gesichert. D.h. je weiter die letzte vollständige Sicherung zurückliegt, desto größer und langsamer wird das
|
||||
Backup.
|
||||
Zur Wiederherstellung werden das letzte vollständige und differentielle Backup benötigt.
|
||||
|
||||
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||||
<script type="text/x-mathjax-config">
|
||||
MathJax.Hub.Config({ tex2jax: {inlineMath: [['$', '$']]}, messageStyle: "none" });
|
||||
</script>
|
||||
|
||||
**Backuphäufigkeit:**
|
||||
Die Backuphäufigkeit ist eine Abwägung aus Risiken, Kosten und Arbeitsaufwand. Dieses muss individuell abgeschätzt
|
||||
werden aufgrund des Datenbankumfangs und der Änderungshäufigkeit der Daten, um eine geeignete Backup-Strategie zu
|
||||
entwerfen. \
|
||||
*Beispiel:*
|
||||
|
||||
- Vorgabe: Datenbank mit 500GB Größe
|
||||
- Anforderungen
|
||||
- min. vierfache Backupkapazität → 2 TB
|
||||
- Backupdauer vollständig: \
|
||||
USB 2.0:$\frac {500GB}{\frac{60MB/s}{1024}} = 8533 sec. \approx 142Min. \approx 2,37 Std.$ \
|
||||
USB 3.0:$\frac {500GB}{\frac{625MB/s}{1024}} = 820 sec. \approx 13,6Min. \approx 0,23 Std.$ \
|
||||
VDSL 100:$\frac {500GB}{\frac{5MB/s}{1024}} = 102400 sec. \approx 1706Min. \approx 28,4 Std.$ \
|
||||
Glasfaser:$\frac {500GB}{\frac{62,5MB/s}{1024}} = 8192 sec. \approx 136,5Min. \approx 2,3 Std.$
|
||||
|
||||
- **1.5 Leistung:** Die Performanceanforderungen an die Datenbank ergibt sich aus verschiedenen Merkmalen. Diese können
|
||||
kombiniert gestellt werden und sind abhängig von den Anforderungen an das System. Eine Analyse der Anwendungsfälle ist
|
||||
notwendig, um die Anforderungen zu spezifizieren.
|
||||
- **Latenz:** Die Datenbank soll Anfragen effizient und in einer akzeptablen Antwortzeit verarbeiten. Typische
|
||||
Datenbankapplikationen, wie z.B. ein Webshop benötigen viele einzelne Zugriffe, wofür jedes Mal ein
|
||||
Kommunikationsprotokoll angewendet wird. Durch viele kleine Datenbankzugriffe wird die Applikation verlangsamt, da
|
||||
auf die Netzwerkkommunikation gewartet wird. Für das Benutzererlebnis eines Webshops ist die Latenz ein wichtiges
|
||||
Merkmal.
|
||||
- **Durchsatz:** Ist eine Metrik für die Anzahl an Transaktionen pro Zeiteinheit. Der Durchsatz ist wichtig bei
|
||||
großen
|
||||
Benutzeraufkommen in einem Webshop.
|
||||
- **Verfügbarkeit:** Eine hohe Verfügbarkeit, also Erreichbarkeit der Datenbank, wird durch Redundanz (mehrfaches
|
||||
Vorhandensein) und Wiederherstellungsmechanismen gewährleistet, damit Daten koninuierlich verfügbar sind.
|
||||
- **Wartbarkeit:** Eine einfach zu wartende Datenbank muss Funktionen zur Überwachung, Diagnose, Wartung,
|
||||
Datensicherung und Wiederherstellung bereitstellen. Durch diese automatisierten Pipelines können andere
|
||||
Eigenschaften, wie z.B. die Verfügbarkeit negativ beeinflusst werden, weil Prozesse die Datenbank blockieren.
|
||||
- **1.6 Integration:** Die Datenbank muss Schnittstellen bereitstellen, um die gespeicherten Daten für eine Anwendung
|
||||
bzw. Systeme zur Verfügung zu stellen.
|
||||
- **API:** Das *Application Programming Interface* ist eine definierte Schnittstelle, welche Methoden und Funktionen
|
||||
bereit stellt, um auf die Datenbank zuzugreifen bzw. um diese zu verwalten.
|
||||
- **REST:** REpresential State Transfer beschreibt eine Schnittstelle, die das http-Protokoll verwendet, wo mit
|
||||
den
|
||||
Methoden GET, POST, PUT, DELETE die Kommunikation realisiert wird.
|
||||
- **SOAP:** Simple Object Access Protocol ist eine Schnittstelle, welche auf XML basiert.
|
||||
- **ODBC:** Open Database Connectivity ist eine standardisierte Schnittstelle zum Austausch zwischen Anwendungen
|
||||
und
|
||||
Datenbanken.
|
||||
- **JDBC:** Java Database Connectivity
|
||||
|
||||
## 2. Datenarten
|
||||
|
||||
Zur Beschreibung von Unternehmen, werden verschiedene Datenarten verwendet.
|
||||
Die folgenden Datenarten sind eine allgemeine Zusammenfassung und sollen das Brainstorming für die projektspezifischen
|
||||
Daten unterstützen.
|
||||
|
||||
- **Stammdaten:** Stammdaten beinhalten die grundsätzlichen Eigenschaften und
|
||||
Informationen von realen Objekten, welche für die periodische Verarbeitung notwendig sind. Ein Stammsatz für Personal
|
||||
besteht z.B. aus einer Personalnummer, dem Mitarbeiternamen, Anschrift und Bankverbindung. \
|
||||
Je nach Anwendungsfall bzw. Geschäftsprozess muss der Inhalt definiert werden, wie z.B. bei Unternehmens-, Kunden-,
|
||||
Material- oder Patientenstammdaten.
|
||||
|
||||
- **Metadaten:** Mit Metadaten werden weitere Daten beschrieben und vereinfachen das Auffinden und Arbeiten mit diesen.
|
||||
Metadaten beinhalten beispielsweise den Verfasser, das Erstellungs- oder Änderungsdatum, die Dateigröße oder den
|
||||
Ablageort. \
|
||||
Mit Metadaten können Datenbestände einfacher und effizienter verwaltet und abgefragt werden.
|
||||
|
||||
- **Transaktionsdaten:** Transaktionsdaten beschreiben eine Veränderung des Zustands, wie z.B. eine Kapitalbewegung oder
|
||||
eine Ein-/Auslieferung aus einem Lager.
|
||||
|
||||
- **Referenzdaten:** Referenzdaten sind eine Teilmenge von Stammdaten und beschreiben die zulässigen Daten. Diese werden
|
||||
nur selten geändert oder angepasst und gelten als konstant. Beispiele für Referenzdaten sind: Postleitzahlen,
|
||||
Kostenstellen, Währungen oder Finanzhierarchien.
|
||||
|
||||
- **Bestandsdaten:** Bestandsdaten sind dauerhafter Veränderung ausgesetzt, da diese z.B. die Artikelmenge in einem
|
||||
Lager oder das Guthaben auf einem Konto beschreiben. Diese korrelieren mit den Transaktionsdaten.
|
||||
|
||||
Diese Datenarten müssen im Kontext des Projektes betrachtet werden und sollen das Brainstorming unterstützen. \
|
||||
*Stammdaten:* Unternehmensname, Anschrift, Branche \
|
||||
*Metadaten:* Verfasser einer Nachricht - Veröffentlichungsdatum; Prüfungsunternehmen - Prüfdatum \
|
||||
*Transaktionsdaten:* Wer hat wann wo gearbeitet? \
|
||||
*Referenzdaten:* Einheit von Metriken (Umsatz, EBIT usw.) \
|
||||
*Bestandsdaten:* Vorstand, Geschäftsführer, Aufsichtsrat
|
||||
|
||||
### 2.1 Welche Daten erwarten wir im Projekt?
|
||||
|
||||
Aus den vorangehenden, allgemeinen Datenarten haben wir Cluster identifiziert, welche im Projekt benötigt werden.
|
||||
Die Kombination aus den folgend aufgeführten Datenclustern ermöglicht eine ganzheitliche Betrachtung und Bewertung der
|
||||
Unternehmen.
|
||||
|
||||
- **Unternehmensstammdaten:** Die Stammdaten beinhalten grundlegende Informationen zu einem Unternehmen, wie z.B. Name,
|
||||
Anschrift, Gesellschaftsform und Branche.
|
||||
|
||||
- **Sentiment daten:** Die Sentiment- oder Stimmungsdaten beschreiben die Aussenwahrnehmung des Unternehmens
|
||||
hinsichtlich
|
||||
der Mitarbeiterzufriedenheit, Nachhaltigkeit und Umweltfreundlichkeit.
|
||||
|
||||
> Mit Sentiment daten können folgende Fragen beantwortet werden:
|
||||
>- Welchen Ruf hat das Unternehmen?
|
||||
>- Wie ist die Aussenwahrnehmung?
|
||||
>- Wie ist die Kundenbindung?
|
||||
|
||||
- **Finanzdaten:** Die Finanzdaten sind Metriken bzw, Indikatoren, um den wirtschaftlichen Erfolg des Unternehmens zu
|
||||
bewerten. Hierzu zählen z.B. Umsatz, EBIT, EBIT Marge, Bilanzsumme, Eigenkapitalanteil, Fremdkapitalanteil,
|
||||
Verschuldungsgrad, Eigenkapitalrentabilität, Umschlaghäufigkeit des Eigenkapitals.
|
||||
|
||||
> Mit Finanzdaten können folgende Fragen beantwortet werden:
|
||||
>- Wie rentabel wirtschaftet das Unternehmen?
|
||||
>- Wie ist der wirtschaftliche Trend?
|
||||
>- Bewerten anhand verschiedener Metriken.
|
||||
|
||||
- **Verflechtungsdaten/Social Graph:** Die Verbindungen bzw. Beziehungen zu Personen oder Unternehmen wird in den
|
||||
Verflechtungsdaten abgelegt. Beziehungen entstehen, wenn eine Person Geschäftsführer, Vorstand, Aufsichtsratmitglied,
|
||||
Prokurist oder Auditor ist und Unternehmen z.B. gemeinsam arbeiten, beliefert wird oder Anteile an einem anderen
|
||||
Unternehmen besitzt.
|
||||
|
||||
> Mit Verflechtungsdaten können folgende Fragen beantwortet werden:
|
||||
>- Gibt es strategische Partnerschaften?
|
||||
>- Wie sind die Lieferketten aufgebaut?
|
||||
>- Wie ist die Qualität der Geschäftsbeziehungen?
|
||||
>- Ist das Unternehmen widerstandsfähig aufgestellt?
|
||||
>- Gibt es Zusammenhänge zu Personen?
|
||||
|
||||
Die abgebildete Mindmap ist nicht vollständig und bildet nicht den finalen Datenumfang des Projekts ab. Es ist eine
|
||||
Momentaufnahme, bevor das relationale Schema entwickelt und die Implementierung begonnen wurde.
|
||||
|
||||

|
||||
|
||||
### 2.2 strukturierte Daten
|
||||
|
||||
Strukturierte Daten liegen in einem definierten Format. Vorab wird ein Schema definiert, um Felder, Datentypen und
|
||||
Reihenfolgen festzulegen und die Daten entsprechend abzulegen.
|
||||
Diese Art von Daten wird z.B. in relationalen Datenbanken verwendet, wobei jede Zeile einer Tabelle einen Datensatz
|
||||
repräsentiert. Die Beziehungen untereinander sind über die Entitäten definiert.
|
||||
Das Beispiel unten zeigt ein einfaches Beispiel, wie die Daten für die Klasse *Company* definiert sind. Mit diesem
|
||||
Schema kann die Datenaufbereitung umgesetzt werden.
|
||||
|
||||
```{mermaid}
|
||||
---
|
||||
title: Structured Data
|
||||
---
|
||||
classDiagram
|
||||
class Company:::styleClass {
|
||||
int ID
|
||||
string Name
|
||||
string Street
|
||||
int ZipCode
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
| Vorteile | Nachteile |
|
||||
|:---------------------------------------------:|:----------------------------------------------------------------:|
|
||||
| einfach nutzbar, da organisiert | Einschränkung der Verwendungsmöglichkeit durch Schema |
|
||||
| bei bekannten Schema sind Werkzeuge vorhanden | begrenze Speichermöglichkeit, da starre Schemata vorgegeben sind |
|
||||
| gut automatisierbar | |
|
||||
|
||||
### 2.3 unstrukturierte Daten
|
||||
|
||||
Unstrukturierte Daten unterliegen keinem Schema, wie z.B. E-Mails, Textdokumente, Blogs, Chats, Bilder, Videos oder
|
||||
Audiodateien.
|
||||
|
||||
- **Textanalyse:** Aus unstrukturierten Texten werden z.B. durch Analyse und Mining Informationen gewonnen, um diese zu
|
||||
extrahieren. Es wird das Vorkommen von bestimmten Wörtern mittels Named Entity Recognition ermittelt oder die Stimmung
|
||||
bzw. das Thema in einem Artikel.
|
||||
- **Audio-/Videoanalyse:** Bei der Verarbeitung unstrukturierter Audio- oder Videodateien werden Objekte, Gesichter,
|
||||
Stimmen oder Muster erkannt, um diese für Sprachassistenten oder autonome Fahrzeuge nutzbar zu machen.
|
||||
|
||||
Eine wichtige Informationsquelle sind unstrukturierte Daten für Explorations- und Analyseaufgaben. Dabei werden
|
||||
Datenquellen wie z.B. E-Mails, RSS-Feeds, Blogs durchsucht, um bestimmte Informationen zu finden oder Zusammenhänge
|
||||
zwischen verschiedenen Quellen herzustellen. Dies ermöglicht tiefe Einsicht in die Daten zu erhalten und unterstützt
|
||||
die Entscheidungsfindung bei unklaren Sachverhalten und die Entdeckung neuer Erkenntnisse.
|
||||
|
||||
| Vorteile | Nachteile |
|
||||
|:-----------------------------------------------------------------:|:-------------------------------------------------------------:|
|
||||
| großes Potenzial Erkenntnisse zu erlangen | aufwändige Bearbeitung notwendig, um Daten nutzbar zu machen |
|
||||
| unbegrenzte Anwendungsmöglichkeiten, da kein Schema vorhanden ist | spezielle Tools zur Aufbereitung notwendig |
|
||||
| | Expertenwissen über die Daten und Datenaufbereitung notwendig |
|
||||
|
||||
## 3. Arten von Datenbanken
|
||||
|
||||
### 3.1 Relationale Datenbank
|
||||
|
||||
Eine relationale Datenbank speichert und verwaltet strukturierte Daten. Dabei werden die Daten in Tabellen organisiert,
|
||||
welche aus Zeilen und Spalten bestehen. \
|
||||
In den Zeilen der Tabellen sind die Datensätze gespeichert, d.h. jede Zeile repräsentiert einen Datensatz. Durch
|
||||
logisches Verbinden der Tabellen können die Beziehungen zwischen den Daten abgebildet werden. \
|
||||
Die wichtigsten Elemente einer relationalen Datenbank werden folgend erklärt:
|
||||
|
||||
**Tabelle:** Eine Tabelle repräsentiert eine Entität bzw. Objekt, wie z.B. Unternehmen, Kunde oder Bestellung. Die
|
||||
Tabelle besteht aus Spalten, welche die Attribute der Entität speichern. \
|
||||
Jede Zeile ist eine Instanz des Objekts und enthält konkrete Werte.
|
||||
|
||||
**Table_Person**
|
||||
|
||||
| **ID** | **Name** | **Age** | **Salary** | **Height** |
|
||||
|--------|----------|---------|------------|------------|
|
||||
| 1 | Tim | 31 | 300.00 | 191.20 |
|
||||
| 2 | Tom | 21 | 400.00 | 181.87 |
|
||||
| 3 | Tam | 51 | 500.00 | 176.54 |
|
||||
|
||||
https://www.sqlservercentral.com/articles/creating-markdown-formatted-text-for-results-from-sql-server-tables
|
||||
|
||||
**Primärschlüssel:** Der Primärschlüssel ist ein eindeutiger Bezeichner für jede einzelne Zeile einer Tabelle und wird
|
||||
zur Identifikation einer einzelnen Zeile benötigt. Im oberen Beispiel ist die Spalte *ID* der Primärschlüssel.
|
||||
|
||||
**Fremdschlüssel:** Ein Fremdschlüssel verweist auf einen Primärschlüssel einer anderen Tabelle, um eine Beziehung
|
||||
zwischen den Tabellen herzustellen. \
|
||||
Im Beispiel bezieht sich die Spalte *customer_id* auf den Primärschlüssel der Tabelle *Table_Person*.
|
||||
|
||||
**Table_Orders**
|
||||
|
||||
| **ID** | **Product** | **total** | **customer_id** |
|
||||
|--------|-------------|-----------|-----------------|
|
||||
| 1 | Paper | 12 | 2 |
|
||||
| 2 | Book | 3 | 2 |
|
||||
| 3 | Marker | 5 | 3 |
|
||||
|
||||
**Beziehungen:** Wie bereits beschrieben, können mit der Verwendung von Fremdschlüsseln Beziehungen zwischen den
|
||||
Tabellen hergestellt werden. \
|
||||
Es gibt verschiedene Beziehungstypen:
|
||||
|
||||
| **Typ** | **Beschreibung** |
|
||||
|:-------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| 1:1 | Jeder Primärschlüsselwert bezieht sich auf nur einen Datensatz. **Beispiel:** Jede Person hat genau eine Bestellung. |
|
||||
| 1:n | Der Primärschlüssel ist eindeutig, tritt in der bezogenen Tabelle 0..n mal auf. **Beispiel:** Jede Person kann keine, eine oder mehrere Bestellungen haben. |
|
||||
| n:n | Jeder Datensatz von beiden Tabellen kann zu beliebig vielen Datensätzen (oder auch zu keinem Datensatz) stehen. Meist wird für diesen Typ eine dritte Tabelle verwendet, welche als Zuordnungs- bzw. Verknüpfungstabelle angelegt wird, da andernfalls keine direkte Verbindung hergestellt werden kann. |
|
||||
|
||||
https://www.ibm.com/docs/de/control-desk/7.6.1.2?topic=structure-database-relationships
|
||||
|
||||
#### 3.1.1 Anlegen von Tabellen
|
||||
|
||||
Der Umgang von relationalen Datenbanken erfolgt mittels SQL. Folgend ein Beispiel zum Anlegen einer Tabelle mit
|
||||
Attributen.
|
||||
|
||||
```sql
|
||||
CREATE TABLE Bildungsstaette
|
||||
(
|
||||
ID INT PRIMARY KEY NOT NULL,
|
||||
Name VARCHAR(255) NOT NULL,
|
||||
Anschrift VARCHAR(255),
|
||||
Art VARCHAR(100)
|
||||
);
|
||||
```
|
||||
|
||||
#### 3.1.2 SQL - Abfrage von relationalen Datenbanken
|
||||
|
||||
Für die Verwaltung und Abfrage wird SQL (Structured Query Language) verwendet.
|
||||
Mit dieser Syntax können Tabellen erstellt, Daten eingefügt, aktualisiert und gelöscht und Daten abgefragt werden.
|
||||
|
||||
**Anzeige aller Attribute einer Tabelle:**
|
||||
|
||||
```sql
|
||||
SELECT *
|
||||
FROM table_name;
|
||||
```
|
||||
|
||||
**Anzeige definierter Attribute einer Tabelle:**
|
||||
|
||||
```sql
|
||||
SELECT column1, column2
|
||||
FROM table_name;
|
||||
```
|
||||
|
||||
**Gefilterte Anzeige einer Tabelle:**
|
||||
|
||||
```sql
|
||||
SELECT *
|
||||
FROM table_name
|
||||
WHERE condition;
|
||||
```
|
||||
|
||||
**Daten aus mehreren Tabellen abrufen (Join):**
|
||||
|
||||
```sql
|
||||
SELECT t1.column1, t2.column2
|
||||
FROM table1 t1
|
||||
JOIN table2 t2 ON t1.id = t2.id;
|
||||
```
|
||||
|
||||
### 3.2 Graphdatenbank
|
||||
|
||||
Eine Graphdatenbank basiert auf dem Graphenkonzept. \
|
||||
Ein Graph besteht aus Knoten und Kanten (Beziehungen), welche die Verbindungen zwischen den Knoten darstellen. \
|
||||
Die Stärke der Graphdatenbank liegt in der Darstellung von komplexen Beziehungen.
|
||||
|
||||
**Knoten:** Jeder Knoten repräsentiert eine Entität bzw. Objekt. Jeder Knoten hat eine eindeutige ID oder Bezeichner, um
|
||||
auf diesen zugreifen zu können. Es können auch Attribute hinterlegt werden, um zusätzliche Informationen zu speichern,
|
||||
wie z.B. Geburtsjahr, Wohnort einer Person.
|
||||
|
||||
**Kanten:** Die Kanten verbinden die Knoten und repräsentieren damit die Beziehungen unter den Objekten. Die Kanten
|
||||
können gerichtet und ungerichtet sein. Bei einer gerichteten Beziehung muss die Richtung vom Quell- zum Zielknoten
|
||||
beachtet werden, wohingegen eine ungerichtete Kante eine symmetrische Beziehung darstellt. \
|
||||
*gerichtete Beziehung:* Ein Unternehmen ist abhängig vom Bericht des Wirtschaftsprüfers. \
|
||||
*ungerichtete Beziehung:** Unternehmen A arbeitet gemeinsam mit Unternehmen B an einem Projekt.
|
||||
|
||||
**Label:** Label werden verwendet, um die Knoten zu kategorisieren/gruppieren. Ein Knoten kann auch mehrere Label
|
||||
besitzen, um die Zugehörigkeit an verschiedenen Kategorien darzustellen (z.B. Unternehmensbranche).
|
||||
|
||||
#### 3.2.1 Erstellung eines Datensatzes
|
||||
|
||||
1. Knotenerstellung: Es wird zuerst ein Knoten erstellt, der die Entität repräsentiert.
|
||||
2. ID: Der Knoten benötigt eine eindeutige Identifikationsnummer, welche automatisch erzeugt oder manuell festgelegt
|
||||
werden kann.
|
||||
3. Knoten einfügen: Wenn die beiden notwendigen Elemente (Knoten und ID) festgelegt sind, kann der Knoten eingefügt
|
||||
werden.
|
||||
4. Beziehungen/Kanten festlegen: Wenn der Knoten Beziehungen zu anderen Knoten hat, können diese hinzugefügt werden.
|
||||
|
||||
**Beispiel:**
|
||||
Folgender Code legt in neo4j zwei Knoten und die entsprechenden Beziehungen an.
|
||||
|
||||
```
|
||||
CREATE
|
||||
(:University {id: 4711, name: 'FH SWF - Iserlohn'}),
|
||||
(:University {id: 1234, name: 'FH SWF - Meschede'})
|
||||
WITH *
|
||||
MATCH (u1:University {id: 4711}), (u2:University {id: 1234})
|
||||
CREATE
|
||||
(u1)-[:cooparates_with]->(u2),
|
||||
(u2)-[:cooparates_with]->(u1)
|
||||
```
|
||||
|
||||

|
||||
|
||||
#### 3.2.2 Cypher - Abfrage von Graphdatenbanken
|
||||
|
||||
Um Daten abzufragen wird die Abfragesprache Cypher verwendet.
|
||||
Es werden folgend nur einige grundlegende Befehle gezeigt.
|
||||
|
||||
**Abfrage aller Knoten**
|
||||
|
||||
```
|
||||
MATCH (n)
|
||||
RETURN n
|
||||
```
|
||||
|
||||
**Abfrage aller Kanten/Beziehungen**
|
||||
|
||||
```
|
||||
MATCH ()-[r]-()
|
||||
RETURN r
|
||||
```
|
||||
|
||||
**Abfrage von Knoten mit definierten Eigenschaften**
|
||||
|
||||
```
|
||||
MATCH (n:Label)
|
||||
WHERE n.property = value
|
||||
RETURN n
|
||||
```
|
||||
|
||||
**Beziehung zwischen zwei Knoten abfragen**
|
||||
|
||||
```
|
||||
MATCH (n1)-[r]->(n2)
|
||||
WHERE n1.property = value1 AND n2.property = value2
|
||||
RETURN r
|
||||
```
|
||||
|
||||
### 3.3 Zeitseriendatenbank
|
||||
|
||||
Zeitserien fallen überall dort an, wo eine Metrik zeitlich betrachtet wird, wie z.B. Umsatz oder EBIT.
|
||||
D.h. zu jedem Messwert gibt es einen zeitlich zugeordneten Zeitstempel, wobei die einzelnen Zeitpunkte zu einer Serie
|
||||
zusammengefasst werden, um den Zusammenhang zu betrachten. \
|
||||
Diese Datenbanken sind spezialisiert auf die Speicherung, Verwaltung und Abfrage von Zeitserien. \
|
||||
Die folgenden Erklärungen beziehen sich auf die InfluxDB.
|
||||
|
||||
**Bucket:** Der Bucket separiert Daten in verschiedene Speicher und ist mit der Datenbank bei relationalen Datenbanken
|
||||
vergleichbar.
|
||||
|
||||
**Datapoint:** Unter dem Bucket werden die Datenpunkte gespeichert. Ein Datapoint setzt sich aus mehreren Elementen
|
||||
zusammen, welche erforderlich oder optional sind:
|
||||
|
||||
| **Element** | **Eigenschaft** |
|
||||
|-------------|----------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Measurement | Datentyp: String<br>Leerzeichen sind verboten<br>Max. 64kB |
|
||||
| Tags | Sind optional<br> Bestehen aus einem Key/Value-Paar <br> Datentyp: String <br>Leerzeichen sind verboten <br> Max. 64 kB |
|
||||
| Fields | Min. 1 Field=value Paar wird benötigt <br> Nicht alle Felder müssen in jedem Punkt vorhanden sein <br> Datentypen: Float, String, Integer, Boolean |
|
||||
| Timestamp | Sind optional <br>Influx schreibt standardmäßig die Systemzeit als Zeitstempel <br>Genauigkeit kann eingestellt werden (Default: Nanosekunden) |
|
||||
|
||||
#### 3.3.1 Erstellung eines Datensatzes
|
||||
|
||||
Die Einrichtung von Zeitseriendatenbanken erfolgt mit der CLI von Influx.
|
||||
|
||||
**Anlegen eines Buckets:**
|
||||
|
||||
```
|
||||
CREATE DATABASE finance
|
||||
```
|
||||
|
||||
#### 3.3.2 FluxQuery
|
||||
|
||||
Zur Abfrage von Datenpunkten gibt es FluxQuery, welche sich stark an SQL orientiert. \
|
||||
|
||||
**Abrufen aller Daten aus Bucket:**
|
||||
|
||||
```
|
||||
from(bucket: "my-bucket")
|
||||
```
|
||||
|
||||
**Festlegen des Zeitbereichs:**
|
||||
|
||||
```
|
||||
range(start: -1h, stop: now())
|
||||
```
|
||||
|
||||
**Filtern nach Bedingungen:**
|
||||
|
||||
```
|
||||
filter(fn: (r) => r._measurement == "temperature")
|
||||
```
|
||||
|
||||
**Transformieren von Datenpunkten:**
|
||||
|
||||
```
|
||||
map(fn: (r) => ({r with temperatureF: r.temperature * 2.34 + 123}))
|
||||
```
|
||||
|
||||
### 3.4 Dokumenten Datenbank <a name="3.4"></a>
|
||||
|
||||
Eine Dokumentendatenbank ist ein System, welches für das Speichern von Dokumenten entwicklet wurde. Es gibt verschiedene
|
||||
Arten von Dokumenten, wie z.B. Textdateien (JSON, HTML, XML) oder PDF.
|
||||
Es muss kein Schema für die Dokumente festgelegt werden, dadurch ist es möglich Dokumente mit verschiedenen Datenfeldern
|
||||
zu speichern.
|
||||
Gleiche oder ähnliche Dokumente werden gemeinsam in *Collections* gespeichert.
|
||||
Die wichtigsten Elemente einer Dokumentendatenbank sind:
|
||||
|
||||
**Database:** Unter Database versteht man einen Container, unter welchem Dokumente gespeichert werden. Dies dient der
|
||||
Isolierung bzw. logischen Trennung von Daten.
|
||||
|
||||
**Collection:** Collections werden verwendet, um Dokumente mit ähnlichen Eigenschaften zusammenzufassen. Da
|
||||
Dokumenten-Datenbanken schemenlos sind, dienen die Collections der Organisation.
|
||||
|
||||
**Document:** Das Dokument ist ein einzelnes Datenobjekt und die kleinste Einheit in einer Dokumenten-DB. Ein Dokument
|
||||
kann z.B. ein JSON mit einer eigenen internen Struktur.
|
||||
|
||||

|
||||
|
||||
#### 3.4.1 Erstellen einer Collection / Ablegen von Dokumenten
|
||||
|
||||
Folgend ein Code-Snippet zum Verbinden mit der Datenbank, Anlegen einer Collection und ablegen von Dokumenten.
|
||||
|
||||
``` python
|
||||
from pymongo import MongoClient
|
||||
|
||||
# Verbindung zur MongoDB-Datenbank herstellen
|
||||
client = MongoClient('mongodb://localhost:27017')
|
||||
|
||||
# erstelle ein Cleint-Objekt zur Datenbank
|
||||
db = client['transparenz']
|
||||
|
||||
# Collection erstellen
|
||||
collection = db['Tagesschau_API']
|
||||
|
||||
# Beispiel-Dokumente einfügen
|
||||
doc1 = {
|
||||
'title': 'BASF wird verkauft!',
|
||||
'content': 'BASF wird an Bayer AG verkauft',
|
||||
'date': '2023-06-22'
|
||||
}
|
||||
|
||||
doc2 = {
|
||||
'title': 'Bayer Aktie erreicht Rekordniveau',
|
||||
'content': 'Aufgrund des Zukaufs von BASF.....',
|
||||
'date': '2023-06-23'
|
||||
}
|
||||
|
||||
# Dokumente in die Collection einfügen
|
||||
collection.insert_one(doc1)
|
||||
collection.insert_one(doc2)
|
||||
|
||||
# Verbindung zur Datenbank schließen
|
||||
client.close()
|
||||
|
||||
```
|
||||
|
||||
### 3.5 Aufbau einer Datenbank
|
||||
|
||||
Vor dem Aufbau einer relationalen Datenbank sollten planerische Schritte durchgeführt werden, um ein System zu
|
||||
entwerfen, dass den Anforderungen gerecht wird. \
|
||||
Die wichtigsten Schritte sind:
|
||||
|
||||
**Anforderungsanalyse:** Identifikation und Definition von Anforderungen an die Datenbank durch Betrachtung des
|
||||
Anwendungsfalls.
|
||||
|
||||
**Datenmodell:** Analysieren der Strukturen und Beziehungen, die sich aus der Anforderungsanalyse ergeben. Auswahl eines
|
||||
Datenbankmodells, welches am besten geeignet ist.
|
||||
|
||||
**Tabellenentwurf:** Basierend auf den identifizierten Anforderungen wird die Tabellenstruktur der Datenbank entworfen.
|
||||
Für jede Tabelle werden Spaltennamen, Datentyp und mögliche Einschränkungen wie Primärschlüssel und Fremdschlüssel
|
||||
definiert.
|
||||
|
||||
**Erstellung der Tabellen:** Wenn der Tabellenentwurf schlüssig ist und bereits diskutiert wurde, können die Tabellen
|
||||
erstellt werden. Es werden die zuvor festgelegten Bezeichner, Datenytpen und Constraints hinzugefügt.
|
||||
|
||||
**Beziehungen festlegen:** Um die Beziehungen zwischen Tabellen festzulegen, werden Fremdschlüssel verwendet. Mit
|
||||
Fremdschlüsseln verknüpft man Tabellen mit den Primärschlüsseln anderer, abhängiger Tabellen.
|
||||
|
||||
## 4. Datenbanken Transparenzregister
|
||||
|
||||
Nachdem die Datencluster identifiziert wurden, welche für das Transparenzregister notwendig sind, wurde Rechereche zu
|
||||
den benötigten Datenquellen betrieben. \
|
||||
Es gibt verschiedene Quellen, mit unterschiedlichen Schnittstellen bzw. Zugriff auf die Daten, z.B. mit API´s oder über
|
||||
Web Scrapping.
|
||||
|
||||
Es wurde eine Architektur definiert, welche den Aufbau der späteren Software skizziert:
|
||||

|
||||
|
||||
Mittels geeigneter Techniken werden Daten aus diversen Quellen extrahiert (Data Extraction) und in der Staging DB
|
||||
gespeichert.
|
||||
Mit unterschiedlichen Daten-Extraktionspipelines (Dazta Loader, Sentiment Analysis, Graph Analysis) werden die Daten aus
|
||||
der Staging DB verarbeitet und die strukturierten und aufbereiteten Daten in der Production DB abgelegt. \
|
||||
Das Frontend kann auf diese strukturierten Daten zugreifen, um diese zu visualisieren.
|
||||
|
||||
### 4.1 Production DB - relationales Datenbankmodell
|
||||
|
||||
Für die Production DB ist eine relationale Datenbank vorgesehen, da diese die Daten organisiert und durch Verwendung von
|
||||
definierten Schemata strukturiert. \
|
||||
Diese Strukturen erleichtern die Wartung und Integration zwischen Back- und Frontend.
|
||||

|
||||
|
||||
Zentrales Element ist die Stammdatentabelle **company**, welche einen zusammengesetzten Primärschlüssel aus der Nummer
|
||||
des Handelsregisters und dem zuständigen Amtsgericht bildet. \
|
||||
Die Handelsregisternummer ist nicht eindeutig und wird deutschlandweit mehrfach vergeben, allerdings nur einfach unter
|
||||
einem Amtsgericht.
|
||||
|
||||
Es schließt sich die Tabelle **finance** an, in welcher die Finanzdaten persistiert werden. Diese steht in einer 1:n
|
||||
Beziehung zur Unternehmenstabelle, da ein Unternehmen viele Finanzdaten haben kann und jeder Datensatz genau einem
|
||||
Unternehmen zugewiesen ist. \
|
||||
Die einzelnen Metriken wurden als Attribute definiert, wodurch es viele NULL-Werte in jeder Zeile gibt. Vorteilhaft bei
|
||||
dieser Notation ist allerdings, dass die Metriken durch den Spaltenbezeichner eindeutig sind.
|
||||
|
||||
Die Tabelle **Sentiment** speichert die Stimmungsdaten zu einem Unternehmen. Auch hier besteht eine 1:n Beziehung zu der
|
||||
Unternehmenstabelle. Es gibt einen eigenen Enumeration-Typ, der die Art der Stimmungsdaten festlegt.
|
||||
|
||||
Die Tabelle **district_court** speichert das Amtsgericht, unter welchen die Unternehmen registriert sind. Diese
|
||||
Information ist wichtig, um mit der Handelsregisternummer und dem Amtsgericht ein Unternehmen eindeutig zu
|
||||
identifizieren.
|
||||
|
||||
Die Tabelle **person** speichert Personen, welche unterschiedliche Beziehungen zu Unternehmen haben können. Daraus
|
||||
ergibt sich eine n:m Beziehung (many-to-many), da jede Person mehrere Beziehungen zu einem Unternehmen haben kann bz.
|
||||
jedes Unternehmen mehrfach mit einer Person in Verbindung steht. \
|
||||
Um diese Relation aufzulösen, wird eine Beziehungstabelle **person_relation** benötigt, um die n:m Beziehung auf zwei 1:
|
||||
n Beziehungen zu reduzieren. Diese enthält die Fremdschlüssel der bezogenen Tabellen, um die Beziehung zu modellieren.
|
||||
|
||||
Abschließend gibt es noch die Tabelle **company_relation**, welche die Verbindung zwischen Unternehmen modelliert.
|
||||
Hierfür wurde ein Enumaration-Typ erzeugt, welcher die Art der Beziehung angibt (wird_beliefert_von, arbeitet_mit,
|
||||
ist_beteiligt_an, hat_Anteile_an).
|
||||
|
||||
### 4.2 Staging DB
|
||||
|
||||
Die Staging DB ist eine dokumentbasierte Datenbank zu Speicherung von unstrukturierten und semi-strukturierten Daten.
|
||||
Sie dient als Zwischenspeicher oder "Rohdatenbank" für die Extraktions-Pipelines.
|
||||
Aufgaben der Staging-DB:
|
||||
|
||||
1. **Datenvorbereitung:** Sammlung und Speicherung von Rohdaten aus verschiedenen Quellen
|
||||
2. **Überprüfung:** Entsprechen die Daten den Anforderungen ggfs. Ermittlung von Fehlern oder Inkonsistenzen
|
||||
3. **Testumgebung:** Die Rohdaten aus der Staging DB können mehrfach verwendet werden, um verschiedene Szenarien und
|
||||
Funktionalitäten der Extraktionspipelines zu erproben
|
||||
4. **Backup:** Wenn sich im Laufe des Projekts eine Datenquelle ändert (z.B. Struktur oder Zugang zum Bundesanzeiger)
|
||||
sind die Daten weiterhin verfügbar oder wenn es Änderungen am Schema der Production DB gibt, kann durch eine Änderung
|
||||
am Data Loader das neue Tabellenschema implementiert werden
|
||||
|
||||
Die Staging DB erhält Collections der unterschiedlichen Quellen, unter welchen die Dokumente gespeichert werden.
|
||||
|
||||

|
||||
|
||||
### 4.3 SQL Alchemy
|
||||
|
||||
SQL Alchemy ist eine Python Bibliothek, um mit relationalen Datenbanken zu kommunizieren.
|
||||
Dieses ORM (Object-Relational-Mapping) Framework bildet die Datenbanktabellen als Pythonklassen an und vereinfacht damit
|
||||
das Erstellen, Lesen, Aktualisieren und Löschen von Daten aus Pythonanwendungen.\
|
||||
wichtige Eigenschaften:
|
||||
|
||||
- erleichterte Entwicklung: durch die Abbildung von Datenbanktabellen als Pythonklassen wird durchgängig Pythoncode
|
||||
verwendet
|
||||
- Flexibilität: Durch Verwendung eines Backend-Treibers für die unterschiedlichen Datenbanken, muss der Code nicht
|
||||
geändert werden. Wenn eine andere Datenbank zum Einsatz kommt, muss nur der Treiber ausgetauscht werden (
|
||||
Plattformunabhängigkeit)
|
||||
- Erhöhung der Produktivität: Es werden keine Kompetenzen für SQL Programierung und Wartung benötigt.
|
||||
|
||||
## 5. Proof of Concept
|
||||
|
||||
### 5.1 Docker
|
||||
|
||||
Für die Umsetzung der bisher vorgestellten theoretischen Betrachtungen wird ein Docker Container verwendet. Dieser
|
||||
Container beinhaltet eine relationale und eine dokumentbasierte Datenbank. \
|
||||
Mit Jupyter Notebooks soll die Implementierung und Befüllung der Datenbank erprobt werden, um als Startpunkt für die
|
||||
anstehende Softwareentwicklung zu dienen.
|
||||
|
||||
```yaml
|
||||
version: "3.8"
|
||||
services:
|
||||
db:
|
||||
image: postgres:14.1-alpine
|
||||
container_name: postgres
|
||||
restart: always
|
||||
ports:
|
||||
- "5432:5432"
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
volumes:
|
||||
- ./PostgreSQL:/var/lib/postgresql/data
|
||||
pgadmin:
|
||||
image: dpage/pgadmin4:7.2
|
||||
container_name: pgadmin4_container
|
||||
restart: always
|
||||
ports:
|
||||
- "5050:80"
|
||||
environment:
|
||||
PGADMIN_DEFAULT_EMAIL: admin@fh-swf.de
|
||||
PGADMIN_DEFAULT_PASSWORD: admin
|
||||
volumes:
|
||||
- ./pgadmin:/var/lib/pgadmin
|
||||
|
||||
mongodb:
|
||||
image: mongo:7.0.0-rc4
|
||||
ports:
|
||||
- '27017:27017'
|
||||
volumes:
|
||||
- ./mongo:/data/db
|
||||
```
|
||||
|
||||
| Eintrag | Beschreibung |
|
||||
|----------|--------------------------------------------------|
|
||||
| version | Version von docker-compose |
|
||||
| services | Definition der Services, welche gestartet werden |
|
||||
|
||||
| Option | Beschreibung |
|
||||
|-------------|---------------------------------------------------------------------|
|
||||
| image | Angabe des zu verwendenden Image |
|
||||
| restart | Option, um Container erneut zu starten, falls dieser gestoppt wurde |
|
||||
| environment | Umgebungsvariablen, wie z.B. Username und Passwort |
|
||||
| Ports | Mapping des Containerports zum Port der Hostmaschine |
|
||||
| volumes | Angabe eines Volumes zum Persistieren der Containerdaten |
|
||||
|
||||
Beim Ausführen der docker-compose werden in diesem Verzeichnis Ordner für die Datenablage angelegt. Da zum
|
||||
Verfassungszeitpunkt noch nicht feststeht, wie im Projekt der Datenaustausch stattfindet, könnten diese Ordner bzw. die
|
||||
Volumes einfach untereinander ausgetauscht werden.
|
||||
|
||||
Zum Starten des Containers den folgenden Befehl ausführen:
|
||||
|
||||
```console
|
||||
docker-compose -f docker-compose.yml up
|
||||
```
|
||||
|
||||
### 5.2 PG Admin
|
||||
|
||||
PG Admin ist ein grafisches Administartionstool für Postgres. Wenn der Container gestartet ist, kann man sich
|
||||
über http://localhost:5050/browser/ mit dem Web-UI verbinden. \
|
||||
Dieses Tool dient lediglich der Überprüfung von Commits der Tabellen und daten.
|
||||
|
||||
Die Anmeldedaten lauten:
|
||||
|
||||
```
|
||||
> User: admin@fh-swf.de
|
||||
> Passwort: admin
|
||||
````
|
||||
|
||||

|
||||
|
||||
Zuerst muss der Server angelegt werden, dafür einen Rechtsklick auf Server und den Button „Register“ auswählen. Im
|
||||
geöffneten Dialog muss die Konfiguration festgelegt werden.
|
||||
|
||||
| Reiter | Parameter | Wert |
|
||||
|------------|-------------------|---------------------------------|
|
||||
| General | Name | postgres |
|
||||
| Connection | Host name/address | postgres (siehe docker-compose) |
|
||||
| Connection | Username | postgres (siehe docker-compose) |
|
||||
| Connection | Password | postgres (siehe docker-compose) |
|
||||
|
||||

|
||||
|
||||
### 5.3 Erstellen von Mock Daten
|
||||
|
||||
**Unternehmensstammdaten:**
|
||||
|
||||
Um das Konzept und den Umgang mit den ausgewählten Datenbanken zu überprüfen, sollen Daten in die Datenbank geschrieben
|
||||
werden. Hierfür wurde auf Statista recherchiert, welches die größten deutschen Unternehmen sind, um einen kleinen Stamm
|
||||
an Unternehmensdaten zu generieren (01_Stammdaten_Unternehmen_HR.csv). /
|
||||
Die Relation zu den Amtsgerichten ist frei erfunden und wurde nicht recherchiert.
|
||||

|
||||
|
||||
**Amtsgerichte:**
|
||||
Die Amtsgerichte sind aus https://www.gerichtsverzeichnis.de/ extrahiert, wobei lediglich 12 Amstgerichte eingefügt
|
||||
wurden (Amtsgerichte.csv).
|
||||
|
||||
**Finanzdaten:** Es wurden für drei Unternehmen (EON, Telekom, BASF) die Finanzdaten bezüglich Umsatz, Ebit und Ebitda
|
||||
auf Statista ermittelt und als separate Dateien gespeichert (BASF_data.csv, Telekom_data.csv, EON_data.csv).
|
||||
|
||||
**Personen:** Die Personentabelle ist frei erfunden. Mit einer Onlinebibliothek wurde 1000 Vor- und Nachnamen erzeugt
|
||||
und gespeichert (Person1000.csv).
|
||||
|
||||
**Personen-Unternehmens-Beziehung:** Diese Tabelle ist zufällig erzeugt und dient lediglich für weitere Experimente.
|
||||
Hierfür wurde ein Python-Skript erstellt, welches mit der mehreren Random-Funktionen die Beziehungen zufälloig
|
||||
generiert.
|
||||
|
||||
**Sentiment:** keine Mock-Daten vorhanden
|
||||
|
||||
**Unternehmens-Unternehmens-Beziehung:** keine Mock-Daten vorhanden
|
||||
|
||||
### 5.4 Anlegen der relationalen Tabellen
|
||||
|
||||
Für das Verbinden zu der Postgre Datenbank und das Anlegen der Tabellen wird ein Jupyter Notebooks verwendet (
|
||||
11_Create_Tables_with_SQL-Alchemy.ipynb).
|
||||
|
||||
Die benötigten Bibliotheken werden importiert und das Erstellen von Tabellen als Python-Objekte beschrieben. \
|
||||
Nach dem Anlegen der Tabellen werden die Mock-Daten in die Datenbank geschrieben. \
|
||||
Eine Überprüfung, ob die Daten abgelegt worden ist sehr einfach mit PGAdmin möglich.
|
||||

|
||||
|
||||
Das grundsätzliche Vorgehen bei der Verwendung von SQLAlchemy ist:
|
||||
|
||||
1. Verbindung zur Datenbank herstellen
|
||||
```python
|
||||
from sqlalchemy import create_engine
|
||||
# Connection URL für postgres
|
||||
url = URL.create(
|
||||
drivername="postgresql",
|
||||
username="postgres",
|
||||
password="postgres",
|
||||
host="localhost",
|
||||
database="postgres")
|
||||
|
||||
# Verbindung zur Datenbank
|
||||
engine = create_engine(database_url)
|
||||
```
|
||||
2. Erstellen einer Klasse als Repräsentation der Tabelle.
|
||||
> Es ist üblich und empfehlenswert die Klassendefinitionen in einer separaten Datei vorzunehmen (model.py), damit
|
||||
diese auch in andere Modulen importiert und verwendet werden können
|
||||
```python
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy import Column, Integer, String
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
class MyClass(Base):
|
||||
__tablename__ = 'company'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
name = Column(String)
|
||||
city = Column(String)
|
||||
```
|
||||
3. Starten einer Session/Verbindung, um Daten lesen und schreiben zu können
|
||||
```python
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
# starte die Verbindung
|
||||
Session = sessionmaker(bind=engine)
|
||||
session = Session()
|
||||
```
|
||||
4. Daten abfragen
|
||||
```python
|
||||
# Alle Daten der Klasse/Tabelle abrufen
|
||||
data = session.query(MyClass).all()
|
||||
```
|
||||
5. Daten speichern, wenn z.B. Datensätze in die Datenbank geschrieben werden, muss dies mit der **commit()**-Funktion
|
||||
ausgeführt werden. Das folgende Snippet iteriert durch einen Dataframe, um jede Zeile in die Datenbank zu schreiben.
|
||||
```python
|
||||
for i in range(len(df)):
|
||||
# get data from dataframe
|
||||
myNewData=MyClass(
|
||||
name = str(df['Name'].iloc[i]),
|
||||
city = str(df['Surname'].iloc[i])
|
||||
)
|
||||
session.add(myNewData)
|
||||
session.commit()
|
||||
```
|
||||
|
||||
### 5.5 Abfragen der Datenbank
|
||||
|
||||
Das folgende Code-Snippet zeigt, wie man eine Abfrage gestaltet.
|
||||
|
||||
```python
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy import Column, Integer, String
|
||||
|
||||
# Erstelle eine SQLite-Datenbankdatei oder gib den Pfad zur vorhandenen Datei an
|
||||
url = URL.create(
|
||||
drivername="postgresql",
|
||||
username="postgres",
|
||||
password="postgres",
|
||||
host="localhost",
|
||||
database="postgres"
|
||||
)
|
||||
|
||||
# Erstelle eine Engine zur Verbindung mit der Datenbank
|
||||
engine = create_engine(url)
|
||||
|
||||
# Erstelle eine Klasse, die eine Tabelle repräsentiert
|
||||
Base = declarative_base()
|
||||
|
||||
|
||||
class Company(Base):
|
||||
__tablename__ = 'company'
|
||||
|
||||
hr = Column(Integer(), nullable=False, primary_key=True)
|
||||
court_id = Column(Integer, ForeignKey("district_court.id"), nullable=False, primary_key=True)
|
||||
name = Column(String(100), nullable=False)
|
||||
street = Column(String(100), nullable=False)
|
||||
zip = Column(Integer(), nullable=False)
|
||||
city = Column(String(100), nullable=False)
|
||||
sector = Column(String(100), nullable=False)
|
||||
|
||||
__table_args__ = (
|
||||
PrimaryKeyConstraint('hr', 'court_id', name='pk_company_hr_court'),
|
||||
)
|
||||
|
||||
|
||||
# starte die Verbindung zur Datenbank
|
||||
Session = sessionmaker(bind=engine)
|
||||
session = Session()
|
||||
|
||||
# Abfrage aller Spalten der Tabelle/Klasse Company
|
||||
Comps = session.query(Company).all()
|
||||
|
||||
# Gebe die Spalten name, hr und court_id der Tabelle company aus
|
||||
for comp in Comps:
|
||||
print(comp.name, comp.hr, comp.court_id)
|
||||
```
|
||||
|
||||
<div style="page-break-after: always;"></div>
|
||||
|
||||
## 6. Zusammenfassung
|
||||
|
||||
Die vorliegende Seminararbeit behandelt das Thema der Datenspeicherung mit Fokus auf dem Projekt Transparenzregister. Es
|
||||
wurde erläutert, warum Daten gespeichert werden und welche Art von Daten es gibt.
|
||||
|
||||
Für das Projekt sind Daten und die Speicherung eine Kernkomponente, um die geforderten Analysen bezüglich
|
||||
Verflechtungen, unternehmerischen Erfolgs und Aussenwahrnehmung zu ermöglichen.
|
||||
|
||||
Es wurden Datencluster definiert und entsprechende Quellen gefunden, welche über geeignete Extraktionspipelines die
|
||||
erforderlichen Informationen extrahieren. Zum Speichern dieser extrahierten Daten wurde ein relationales Modell
|
||||
erarbeitet, um ein Konzept für die folgende Implementierung zu haben.
|
||||
|
||||
Um das Konzept zu überprüfen, wurde ein Proof of Concept durchgeführt, um geeignete Werkzeuge zu erproben und das Modell
|
||||
auf seine Tauglichkeit zu überprüfen.
|
||||
|
||||
Hierbei wurde ein Dockercontainer eingesetzt, um die Datenbankumgebung bereitzustellen. Mithilfe der
|
||||
SQL-Alchemy-Bibliothek, wurde die Tabellen innerhalb der Datenbank erstellt.
|
||||
|
||||
Anschließend wurden die Tabellen mit eigenen Mock-Daten befüllt, um die Funktionalität der Datenbank zu testen.
|
||||
|
||||
Insgesamt bietet die Seminararbeit einen umfassenden Überblick über die Bedeutung der Datenspeicherung und die
|
||||
verschiedenen Arten von Datenbanken.
|
||||
Es wurde ein erstes relationales Modell und ein High level design für die Softwarearchitektur erarbeitet.
|
||||
Diese Arbeit hat grundsätzliche Fragen geklärt und Verständnis für die Datenspeicherung im Zusammenhang mit dem Projekt
|
||||
Transparenzregister geschaffen und unterstützt die weitere Entwicklung.
|
||||
|
||||
<div style="page-break-after: always;"></div>
|
||||
|
||||
## Quellen
|
||||
|
||||
- Klug, Uwe: SQL-Der Einstieg in die deklarative Programmierung, 2. Auflage, Dortmund, Springer, 2017
|
||||
- Steiner, Rene: Grundkurs relationale Datenbanken, 10. Auflage, Wiesbaden, Springer, 2021
|
||||
- https://backupchain.de/daten-backup-tipps-3-wie-oft-daten-sichern/
|
||||
- https://www.talend.com/de/resources/strukturierte-vs-unstrukturierte-daten/
|
||||
- https://www.sqlservercentral.com/articles/creating-markdown-formatted-text-for-results-from-sql-server-tables
|
||||
- https://www.sqlalchemy.org/
|
||||
- https://medium.com/@arthurapp98/using-sqlalchemy-to-create-and-populate-a-postgresql-database-with-excel-data-eb6049d93402
|
@ -1,13 +0,0 @@
|
||||
HR;Amtsgericht;Name;Strasse;PLZ;Stadt;Branche
|
||||
12334;2;Volkswagen;Berliner Ring 2;38440;Wolfsburg;Automobil
|
||||
64566;2;Mercedes-Benz Group;Mercedesstra<72>e 120;70372;Stuttgart;Automobil
|
||||
5433;3;Allianz;Reinsburgstra<72>e 19;70178;Stuttgart;Versicherung, Finanzdienstleistung
|
||||
12435;4;BMW Group;Petuelring 130;80809;M<>nchen;Automobil
|
||||
12336;5;Deutsche Telekom;Landgrabenweg 151;53227;Bonn;Telekommunikation, Informationstechnologie
|
||||
559;6;Deutsche Post DHL Group;Charles-de-Gaulle-Str. 20;53113;Bonn;Logistik
|
||||
555;7;Bosch Group;Robert-Bosch-Platz 1;70839;Gerlingen-Schillerh<72>he;Kraftfahrzeugtechnik, Industrietechnik, Gebrauchsg<73>ter, Energie- und Geb<65>udetechnik
|
||||
12384;8;BASF;Carl-Bosch-Stra<72>e 38;67056;Ludwigshafen;Chemie
|
||||
64345;9;E.ON;Arnulfstra<72>e 203;80634;M<>nchen;Energie
|
||||
4344;10;Munich Re Group;K<>niginstr. 107;80802;M<>nchen;Versicherung
|
||||
866;11;Siemens;Werner-von-Siemens-Stra<72>e 1;80333;M<>nchen;Automatisierung, Digitalisierung
|
||||
9875;12;Deutsche Bahn;Potsdamer Platz 2;10785;Berlin;Transport, Logistik
|
|
@ -1,13 +0,0 @@
|
||||
HR;Amtsgericht;Name;Strasse;PLZ;Stadt;Branche
|
||||
12334;2;Volkswagen;Berliner Ring 2;38440;Wolfsburg;Automobil
|
||||
64566;2;Mercedes-Benz Group;Mercedesstra<72>e 120;70372;Stuttgart;Automobil
|
||||
5433;3;Allianz;Reinsburgstra<72>e 19;70178;Stuttgart;Versicherung, Finanzdienstleistung
|
||||
12334;4;BMW Group;Petuelring 130;80809;M<>nchen;Automobil
|
||||
12336;5;Deutsche Telekom;Landgrabenweg 151;53227;Bonn;Telekommunikation, Informationstechnologie
|
||||
555;6;Deutsche Post DHL Group;Charles-de-Gaulle-Str. 20;53113;Bonn;Logistik
|
||||
555;7;Bosch Group;Robert-Bosch-Platz 1;70839;Gerlingen-Schillerh<72>he;Kraftfahrzeugtechnik, Industrietechnik, Gebrauchsg<73>ter, Energie- und Geb<65>udetechnik
|
||||
12384;8;BASF;Carl-Bosch-Stra<72>e 38;67056;Ludwigshafen;Chemie
|
||||
64345;9;E.ON;Arnulfstra<72>e 203;80634;M<>nchen;Energie
|
||||
4344;1;Munich Re Group;K<>niginstr. 107;80802;M<>nchen;Versicherung
|
||||
866;1;Siemens;Werner-von-Siemens-Stra<72>e 1;80333;M<>nchen;Automatisierung, Digitalisierung
|
||||
9875;1;Deutsche Bahn;Potsdamer Platz 2;10785;Berlin;Transport, Logistik
|
|
@ -1,15 +0,0 @@
|
||||
Stadt;Name
|
||||
Aschaffenburg;Amtsgericht Aschaffenburg
|
||||
Bamberg;Amtsgericht Bamberg
|
||||
Bayreuth;Amtsgericht Bayreuth
|
||||
Duesseldorf;Amtsgericht Duesseldorf
|
||||
Duisburg;Amtsgericht Duisburg
|
||||
Duisburg;Amtsgericht Duisburg-Hamborn
|
||||
Duisburg;Amtsgericht Duisburg-Ruhrort
|
||||
Oberhausen;Amtsgericht Oberhausen
|
||||
Wuppertal;Amtsgericht Wuppertal
|
||||
Berlin;Amtsgericht Mitte
|
||||
Berlin;Amtsgericht Ost
|
||||
Berlin;Amtsgericht West
|
||||
Berlin;Amtsgericht Nord
|
||||
Berlin;Amtsgericht Sued
|
|
@ -1,25 +0,0 @@
|
||||
Company_HR;Company_Court;Jahr;Umsatz;Ebit;EBITDA
|
||||
;12384;8;1999;29473;;
|
||||
;12384;8;2000;35946;;
|
||||
;12384;8;2001;32500;;
|
||||
;12384;8;2002;32216;;
|
||||
;12384;8;2003;33361;;
|
||||
;12384;8;2004;37537;;
|
||||
;12384;8;2005;42745;5830;
|
||||
;12384;8;2006;52610;6750;
|
||||
;12384;8;2007;57951;7316;
|
||||
;12384;8;2008;62304;6463;9562
|
||||
;12384;8;2009;50693;3677;7388
|
||||
;12384;8;2010;63873;7761;11131
|
||||
;12384;8;2011;73497;8586;11993
|
||||
;12384;8;2012;72129;6742;10009
|
||||
;12384;8;2013;73973;7160;10432
|
||||
;12384;8;2014;74326;7626;11043
|
||||
;12384;8;2015;70449;6248;10649
|
||||
;12384;8;2016;57550;6275;10526
|
||||
;12384;8;2017;61223;7587;10765
|
||||
;12384;8;2018;60220;5974;8970
|
||||
;12384;8;2019;59316;4201;8185
|
||||
;12384;8;2020;59149;-191;6494
|
||||
;12384;8;2021;78598;7677;11355
|
||||
;12384;8;2022;87327;6548;10748
|
|
@ -1,17 +0,0 @@
|
||||
Company_HR;Company_Court;Jahr;Umsatz;Ebit;EBITDA
|
||||
;64345;9;2007;66912;;
|
||||
;64345;9;2008;84873;;
|
||||
;64345;9;2009;79974;;
|
||||
;64345;9;2010;92863;;
|
||||
;64345;9;2011;112954;;
|
||||
;64345;9;2012;132093;7010;
|
||||
;64345;9;2013;119615;5640;
|
||||
;64345;9;2014;113095;4700;
|
||||
;64345;9;2015;42656;3600;
|
||||
;64345;9;2016;38173;3100;
|
||||
;64345;9;2017;37965;3100;
|
||||
;64345;9;2018;30084;2990;4840
|
||||
;64345;9;2019;41284;3220;5558
|
||||
;64345;9;2020;60944;3780;6905
|
||||
;64345;9;2021;77358;4720;7889
|
||||
;64345;9;2022;115660;5200;8059
|
|
@ -1,13 +0,0 @@
|
||||
Name;Straße;PLZ;Stadt;Branche
|
||||
Volkswagen;Berliner Ring 2;38440;Wolfsburg;Automobil
|
||||
Mercedes-Benz Group;Mercedesstraße 120;70372;Stuttgart;Automobil
|
||||
Allianz;Reinsburgstraße 19;70178;Stuttgart;Versicherung, Finanzdienstleistung
|
||||
BMW Group;Petuelring 130;80809;München;Automobil
|
||||
Deutsche Telekom;Landgrabenweg 151;53227;Bonn;Telekommunikation, Informationstechnologie
|
||||
Deutsche Post DHL Group;Charles-de-Gaulle-Str. 20;53113;Bonn;Logistik
|
||||
Bosch Group;Robert-Bosch-Platz 1;70839;Gerlingen-Schillerhöhe;Kraftfahrzeugtechnik, Industrietechnik, Gebrauchsgüter, Energie- und Gebäudetechnik
|
||||
BASF;Carl-Bosch-Straße 38;67056;Ludwigshafen;Chemie
|
||||
E.ON;Arnulfstraße 203;80634;München;Energie
|
||||
Munich Re Group;Königinstr. 107;80802;München;Versicherung
|
||||
Siemens;Werner-von-Siemens-Straße 1;80333;München;Automatisierung, Digitalisierung
|
||||
Deutsche Bahn;Potsdamer Platz 2;10785;Berlin;Transport, Logistik
|
|
@ -1,480 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"id": "dbd6eae9",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import numpy as np\n",
|
||||
"import pandas as pd\n",
|
||||
"import ipywidgets as widgets\n",
|
||||
"\n",
|
||||
"pd.options.plotting.backend = \"plotly\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"id": "8b447b09",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df = pd.read_csv(\"Telekom_Data_NewOrder.csv\", sep=\";\", decimal=\",\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"id": "5fc7b7d2",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
"<style scoped>\n",
|
||||
" .dataframe tbody tr th:only-of-type {\n",
|
||||
" vertical-align: middle;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe tbody tr th {\n",
|
||||
" vertical-align: top;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe thead th {\n",
|
||||
" text-align: right;\n",
|
||||
" }\n",
|
||||
"</style>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
" <th></th>\n",
|
||||
" <th>Metrik</th>\n",
|
||||
" <th>Datum</th>\n",
|
||||
" <th>Summe [Milliarden €]</th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2005</td>\n",
|
||||
" <td>59.600</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>1</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2006</td>\n",
|
||||
" <td>61.300</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>2</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2007</td>\n",
|
||||
" <td>62.500</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>3</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2008</td>\n",
|
||||
" <td>61.700</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>4</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2009</td>\n",
|
||||
" <td>64.600</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>5</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2010</td>\n",
|
||||
" <td>62.420</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>6</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2011</td>\n",
|
||||
" <td>58.650</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>7</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2012</td>\n",
|
||||
" <td>58.170</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>8</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2013</td>\n",
|
||||
" <td>60.130</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>9</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2014</td>\n",
|
||||
" <td>62.660</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>10</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2015</td>\n",
|
||||
" <td>69.230</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>11</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2016</td>\n",
|
||||
" <td>73.100</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>12</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2017</td>\n",
|
||||
" <td>74.950</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>13</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2018</td>\n",
|
||||
" <td>75.660</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>14</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2019</td>\n",
|
||||
" <td>80.530</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>15</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2020</td>\n",
|
||||
" <td>99.950</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>16</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2021</td>\n",
|
||||
" <td>107.610</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>17</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2022</td>\n",
|
||||
" <td>114.200</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>18</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2005</td>\n",
|
||||
" <td>7.600</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>19</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2006</td>\n",
|
||||
" <td>5.300</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>20</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2007</td>\n",
|
||||
" <td>5.300</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>21</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2008</td>\n",
|
||||
" <td>7.000</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>22</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2009</td>\n",
|
||||
" <td>6.000</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>23</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2010</td>\n",
|
||||
" <td>5.510</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>24</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2011</td>\n",
|
||||
" <td>5.560</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>25</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2012</td>\n",
|
||||
" <td>-3.960</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>26</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2013</td>\n",
|
||||
" <td>4.930</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>27</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2014</td>\n",
|
||||
" <td>7.250</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>28</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2015</td>\n",
|
||||
" <td>7.030</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>29</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2016</td>\n",
|
||||
" <td>9.160</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>30</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2017</td>\n",
|
||||
" <td>9.380</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>31</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2018</td>\n",
|
||||
" <td>8.000</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>32</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2019</td>\n",
|
||||
" <td>9.460</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>33</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2020</td>\n",
|
||||
" <td>12.370</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>34</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2021</td>\n",
|
||||
" <td>12.580</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>35</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2022</td>\n",
|
||||
" <td>15.410</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>36</th>\n",
|
||||
" <td>EBITDA</td>\n",
|
||||
" <td>01.01.2018</td>\n",
|
||||
" <td>23.333</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>37</th>\n",
|
||||
" <td>EBITDA</td>\n",
|
||||
" <td>01.01.2019</td>\n",
|
||||
" <td>24.731</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>38</th>\n",
|
||||
" <td>EBITDA</td>\n",
|
||||
" <td>01.01.2020</td>\n",
|
||||
" <td>35.017</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>39</th>\n",
|
||||
" <td>EBITDA</td>\n",
|
||||
" <td>01.01.2021</td>\n",
|
||||
" <td>37.330</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>40</th>\n",
|
||||
" <td>EBITDA</td>\n",
|
||||
" <td>01.01.2022</td>\n",
|
||||
" <td>40.208</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"text/plain": [
|
||||
" Metrik Datum Summe [Milliarden €]\n",
|
||||
"0 Umsatz 01.01.2005 59.600\n",
|
||||
"1 Umsatz 01.01.2006 61.300\n",
|
||||
"2 Umsatz 01.01.2007 62.500\n",
|
||||
"3 Umsatz 01.01.2008 61.700\n",
|
||||
"4 Umsatz 01.01.2009 64.600\n",
|
||||
"5 Umsatz 01.01.2010 62.420\n",
|
||||
"6 Umsatz 01.01.2011 58.650\n",
|
||||
"7 Umsatz 01.01.2012 58.170\n",
|
||||
"8 Umsatz 01.01.2013 60.130\n",
|
||||
"9 Umsatz 01.01.2014 62.660\n",
|
||||
"10 Umsatz 01.01.2015 69.230\n",
|
||||
"11 Umsatz 01.01.2016 73.100\n",
|
||||
"12 Umsatz 01.01.2017 74.950\n",
|
||||
"13 Umsatz 01.01.2018 75.660\n",
|
||||
"14 Umsatz 01.01.2019 80.530\n",
|
||||
"15 Umsatz 01.01.2020 99.950\n",
|
||||
"16 Umsatz 01.01.2021 107.610\n",
|
||||
"17 Umsatz 01.01.2022 114.200\n",
|
||||
"18 EBIT 01.01.2005 7.600\n",
|
||||
"19 EBIT 01.01.2006 5.300\n",
|
||||
"20 EBIT 01.01.2007 5.300\n",
|
||||
"21 EBIT 01.01.2008 7.000\n",
|
||||
"22 EBIT 01.01.2009 6.000\n",
|
||||
"23 EBIT 01.01.2010 5.510\n",
|
||||
"24 EBIT 01.01.2011 5.560\n",
|
||||
"25 EBIT 01.01.2012 -3.960\n",
|
||||
"26 EBIT 01.01.2013 4.930\n",
|
||||
"27 EBIT 01.01.2014 7.250\n",
|
||||
"28 EBIT 01.01.2015 7.030\n",
|
||||
"29 EBIT 01.01.2016 9.160\n",
|
||||
"30 EBIT 01.01.2017 9.380\n",
|
||||
"31 EBIT 01.01.2018 8.000\n",
|
||||
"32 EBIT 01.01.2019 9.460\n",
|
||||
"33 EBIT 01.01.2020 12.370\n",
|
||||
"34 EBIT 01.01.2021 12.580\n",
|
||||
"35 EBIT 01.01.2022 15.410\n",
|
||||
"36 EBITDA 01.01.2018 23.333\n",
|
||||
"37 EBITDA 01.01.2019 24.731\n",
|
||||
"38 EBITDA 01.01.2020 35.017\n",
|
||||
"39 EBITDA 01.01.2021 37.330\n",
|
||||
"40 EBITDA 01.01.2022 40.208"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"df"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "d5c6c68d",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---------------------------------\n",
|
||||
"# Schreibe Unternehmensdaten in PostgreSQL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"id": "6c09bdca",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import psycopg2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "383fb9a9",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Verbinde zur Datenbank"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"id": "3e1ea224",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Database connected successfully\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"conn = psycopg2.connect(\n",
|
||||
" host=\"localhost\", database=\"transparenz\", user=\"postgres\", password=\"postgres\"\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"print(\"Database connected successfully\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "22b9ab1d",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Iteriere durch Dataframe und schreibe Datensätze in Tabelle *Company*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"id": "961ac836",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"cur = conn.cursor()\n",
|
||||
"\n",
|
||||
"PK_ID = 5 # BASF hat den PK 8, deshalb wird dieser manuell hinzugefügt\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"for i in range(len(df)):\n",
|
||||
" # get data from dataframe\n",
|
||||
" kind_of = str(df[\"Metrik\"].iloc[i])\n",
|
||||
" date = str(df[\"Datum\"].iloc[i])\n",
|
||||
" amount = float(df[\"Summe [Milliarden €]\"].iloc[i])\n",
|
||||
"\n",
|
||||
" postgres_insert_query = (\n",
|
||||
" \"\"\" INSERT INTO finance (company_id,kind_of, date, sum) VALUES (%s,%s,%s,%s)\"\"\"\n",
|
||||
" )\n",
|
||||
" record_to_insert = (PK_ID, kind_of, date, amount)\n",
|
||||
" cur.execute(postgres_insert_query, record_to_insert)\n",
|
||||
" # print(postgres_insert_query, record_to_insert)\n",
|
||||
"\n",
|
||||
"conn.commit()\n",
|
||||
"conn.close()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "46b5be7c",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.8"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
@ -1,417 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"id": "dbd6eae9",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import numpy as np\n",
|
||||
"import pandas as pd\n",
|
||||
"import ipywidgets as widgets\n",
|
||||
"\n",
|
||||
"pd.options.plotting.backend = \"plotly\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"id": "8b447b09",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df = pd.read_csv(\"EON_Data_NewOrder.csv\", sep=\";\", decimal=\",\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"id": "5fc7b7d2",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
"<style scoped>\n",
|
||||
" .dataframe tbody tr th:only-of-type {\n",
|
||||
" vertical-align: middle;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe tbody tr th {\n",
|
||||
" vertical-align: top;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe thead th {\n",
|
||||
" text-align: right;\n",
|
||||
" }\n",
|
||||
"</style>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
" <th></th>\n",
|
||||
" <th>Metrik</th>\n",
|
||||
" <th>Datum</th>\n",
|
||||
" <th>Summe [Milliarden €]</th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2007</td>\n",
|
||||
" <td>66.912</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>1</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2008</td>\n",
|
||||
" <td>84.873</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>2</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2009</td>\n",
|
||||
" <td>79.974</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>3</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2010</td>\n",
|
||||
" <td>92.863</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>4</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2011</td>\n",
|
||||
" <td>112.954</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>5</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2012</td>\n",
|
||||
" <td>132.093</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>6</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2013</td>\n",
|
||||
" <td>119.615</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>7</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2014</td>\n",
|
||||
" <td>113.095</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>8</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2015</td>\n",
|
||||
" <td>42.656</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>9</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2016</td>\n",
|
||||
" <td>38.173</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>10</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2017</td>\n",
|
||||
" <td>37.965</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>11</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2018</td>\n",
|
||||
" <td>30.084</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>12</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2019</td>\n",
|
||||
" <td>41.284</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>13</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2020</td>\n",
|
||||
" <td>60.944</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>14</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2021</td>\n",
|
||||
" <td>77.358</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>15</th>\n",
|
||||
" <td>Umsatz</td>\n",
|
||||
" <td>01.01.2022</td>\n",
|
||||
" <td>115.660</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>16</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2012</td>\n",
|
||||
" <td>7.010</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>17</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2013</td>\n",
|
||||
" <td>5.640</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>18</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2014</td>\n",
|
||||
" <td>4.700</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>19</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2015</td>\n",
|
||||
" <td>3.600</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>20</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2016</td>\n",
|
||||
" <td>3.100</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>21</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2017</td>\n",
|
||||
" <td>3.100</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>22</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2018</td>\n",
|
||||
" <td>2.990</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>23</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2019</td>\n",
|
||||
" <td>3.220</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>24</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2020</td>\n",
|
||||
" <td>3.780</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>25</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2021</td>\n",
|
||||
" <td>4.720</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>26</th>\n",
|
||||
" <td>EBIT</td>\n",
|
||||
" <td>01.01.2022</td>\n",
|
||||
" <td>5.200</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>27</th>\n",
|
||||
" <td>EBITDA</td>\n",
|
||||
" <td>01.01.2018</td>\n",
|
||||
" <td>4.840</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>28</th>\n",
|
||||
" <td>EBITDA</td>\n",
|
||||
" <td>01.01.2019</td>\n",
|
||||
" <td>5.558</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>29</th>\n",
|
||||
" <td>EBITDA</td>\n",
|
||||
" <td>01.01.2020</td>\n",
|
||||
" <td>6.905</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>30</th>\n",
|
||||
" <td>EBITDA</td>\n",
|
||||
" <td>01.01.2021</td>\n",
|
||||
" <td>7.889</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>31</th>\n",
|
||||
" <td>EBITDA</td>\n",
|
||||
" <td>01.01.2022</td>\n",
|
||||
" <td>8.059</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"text/plain": [
|
||||
" Metrik Datum Summe [Milliarden €]\n",
|
||||
"0 Umsatz 01.01.2007 66.912\n",
|
||||
"1 Umsatz 01.01.2008 84.873\n",
|
||||
"2 Umsatz 01.01.2009 79.974\n",
|
||||
"3 Umsatz 01.01.2010 92.863\n",
|
||||
"4 Umsatz 01.01.2011 112.954\n",
|
||||
"5 Umsatz 01.01.2012 132.093\n",
|
||||
"6 Umsatz 01.01.2013 119.615\n",
|
||||
"7 Umsatz 01.01.2014 113.095\n",
|
||||
"8 Umsatz 01.01.2015 42.656\n",
|
||||
"9 Umsatz 01.01.2016 38.173\n",
|
||||
"10 Umsatz 01.01.2017 37.965\n",
|
||||
"11 Umsatz 01.01.2018 30.084\n",
|
||||
"12 Umsatz 01.01.2019 41.284\n",
|
||||
"13 Umsatz 01.01.2020 60.944\n",
|
||||
"14 Umsatz 01.01.2021 77.358\n",
|
||||
"15 Umsatz 01.01.2022 115.660\n",
|
||||
"16 EBIT 01.01.2012 7.010\n",
|
||||
"17 EBIT 01.01.2013 5.640\n",
|
||||
"18 EBIT 01.01.2014 4.700\n",
|
||||
"19 EBIT 01.01.2015 3.600\n",
|
||||
"20 EBIT 01.01.2016 3.100\n",
|
||||
"21 EBIT 01.01.2017 3.100\n",
|
||||
"22 EBIT 01.01.2018 2.990\n",
|
||||
"23 EBIT 01.01.2019 3.220\n",
|
||||
"24 EBIT 01.01.2020 3.780\n",
|
||||
"25 EBIT 01.01.2021 4.720\n",
|
||||
"26 EBIT 01.01.2022 5.200\n",
|
||||
"27 EBITDA 01.01.2018 4.840\n",
|
||||
"28 EBITDA 01.01.2019 5.558\n",
|
||||
"29 EBITDA 01.01.2020 6.905\n",
|
||||
"30 EBITDA 01.01.2021 7.889\n",
|
||||
"31 EBITDA 01.01.2022 8.059"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"df"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "d5c6c68d",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---------------------------------\n",
|
||||
"# Schreibe Unternehmensdaten in PostgreSQL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"id": "6c09bdca",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import psycopg2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "383fb9a9",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Verbinde zur Datenbank"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"id": "3e1ea224",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Database connected successfully\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"conn = psycopg2.connect(\n",
|
||||
" host=\"localhost\", database=\"transparenz\", user=\"postgres\", password=\"postgres\"\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"print(\"Database connected successfully\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "22b9ab1d",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Iteriere durch Dataframe und schreibe Datensätze in Tabelle *Company*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"id": "961ac836",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"cur = conn.cursor()\n",
|
||||
"\n",
|
||||
"PK_ID = 9 # BASF hat den PK 8, deshalb wird dieser manuell hinzugefügt\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"for i in range(len(df)):\n",
|
||||
" # get data from dataframe\n",
|
||||
" kind_of = str(df[\"Metrik\"].iloc[i])\n",
|
||||
" date = str(df[\"Datum\"].iloc[i])\n",
|
||||
" amount = float(df[\"Summe [Milliarden €]\"].iloc[i])\n",
|
||||
"\n",
|
||||
" postgres_insert_query = (\n",
|
||||
" \"\"\" INSERT INTO finance (company_id,kind_of, date, sum) VALUES (%s,%s,%s,%s)\"\"\"\n",
|
||||
" )\n",
|
||||
" record_to_insert = (PK_ID, kind_of, date, amount)\n",
|
||||
" cur.execute(postgres_insert_query, record_to_insert)\n",
|
||||
" # print(postgres_insert_query, record_to_insert)\n",
|
||||
"\n",
|
||||
"conn.commit()\n",
|
||||
"conn.close()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "46b5be7c",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.8"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
Stadt;Name
|
||||
Aschaffenburg;Amtsgericht Aschaffenburg
|
||||
Bamberg;Amtsgericht Bamberg
|
||||
Bayreuth;Amtsgericht Bayreuth
|
||||
Duesseldorf;Amtsgericht Duesseldorf
|
||||
Duisburg;Amtsgericht Duisburg
|
||||
Duisburg;Amtsgericht Duisburg-Hamborn
|
||||
Duisburg;Amtsgericht Duisburg-Ruhrort
|
||||
Oberhausen;Amtsgericht Oberhausen
|
||||
Wuppertal;Amtsgericht Wuppertal
|
|
@ -1,58 +0,0 @@
|
||||
Metrik;Datum;Summe [Milliarden €]
|
||||
Umsatz;01.01.1999;29,473
|
||||
Umsatz;01.01.2000;35,946
|
||||
Umsatz;01.01.2001;32,5
|
||||
Umsatz;01.01.2002;32,216
|
||||
Umsatz;01.01.2003;33,361
|
||||
Umsatz;01.01.2004;37,537
|
||||
Umsatz;01.01.2005;42,745
|
||||
Umsatz;01.01.2006;52,61
|
||||
Umsatz;01.01.2007;57,951
|
||||
Umsatz;01.01.2008;62,304
|
||||
Umsatz;01.01.2009;50,693
|
||||
Umsatz;01.01.2010;63,873
|
||||
Umsatz;01.01.2011;73,497
|
||||
Umsatz;01.01.2012;72,129
|
||||
Umsatz;01.01.2013;73,973
|
||||
Umsatz;01.01.2014;74,326
|
||||
Umsatz;01.01.2015;70,449
|
||||
Umsatz;01.01.2016;57,55
|
||||
Umsatz;01.01.2017;61,223
|
||||
Umsatz;01.01.2018;60,22
|
||||
Umsatz;01.01.2019;59,316
|
||||
Umsatz;01.01.2020;59,149
|
||||
Umsatz;01.01.2021;78,598
|
||||
Umsatz;01.01.2022;87,327
|
||||
EBIT;01.01.2005;5,83
|
||||
EBIT;01.01.2006;6,75
|
||||
EBIT;01.01.2007;7,316
|
||||
EBIT;01.01.2008;6,463
|
||||
EBIT;01.01.2009;3,677
|
||||
EBIT;01.01.2010;7,761
|
||||
EBIT;01.01.2011;8,586
|
||||
EBIT;01.01.2012;6,742
|
||||
EBIT;01.01.2013;7,16
|
||||
EBIT;01.01.2014;7,626
|
||||
EBIT;01.01.2015;6,248
|
||||
EBIT;01.01.2016;6,275
|
||||
EBIT;01.01.2017;7,587
|
||||
EBIT;01.01.2018;5,974
|
||||
EBIT;01.01.2019;4,201
|
||||
EBIT;01.01.2020;-0,191
|
||||
EBIT;01.01.2021;7,677
|
||||
EBIT;01.01.2022;6,548
|
||||
EBITDA;01.01.2008;9,562
|
||||
EBITDA;01.01.2009;7,388
|
||||
EBITDA;01.01.2010;11,131
|
||||
EBITDA;01.01.2011;11,993
|
||||
EBITDA;01.01.2012;10,009
|
||||
EBITDA;01.01.2013;10,432
|
||||
EBITDA;01.01.2014;11,043
|
||||
EBITDA;01.01.2015;10,649
|
||||
EBITDA;01.01.2016;10,526
|
||||
EBITDA;01.01.2017;10,765
|
||||
EBITDA;01.01.2018;8,97
|
||||
EBITDA;01.01.2019;8,185
|
||||
EBITDA;01.01.2020;6,494
|
||||
EBITDA;01.01.2021;11,355
|
||||
EBITDA;01.01.2022;10,748
|
|
@ -1,33 +0,0 @@
|
||||
Metrik;Datum;Summe [Milliarden €]
|
||||
Umsatz;01.01.2007;66,912
|
||||
Umsatz;01.01.2008;84,873
|
||||
Umsatz;01.01.2009;79,974
|
||||
Umsatz;01.01.2010;92,863
|
||||
Umsatz;01.01.2011;112,954
|
||||
Umsatz;01.01.2012;132,093
|
||||
Umsatz;01.01.2013;119,615
|
||||
Umsatz;01.01.2014;113,095
|
||||
Umsatz;01.01.2015;42,656
|
||||
Umsatz;01.01.2016;38,173
|
||||
Umsatz;01.01.2017;37,965
|
||||
Umsatz;01.01.2018;30,084
|
||||
Umsatz;01.01.2019;41,284
|
||||
Umsatz;01.01.2020;60,944
|
||||
Umsatz;01.01.2021;77,358
|
||||
Umsatz;01.01.2022;115,66
|
||||
EBIT;01.01.2012;7,01
|
||||
EBIT;01.01.2013;5,64
|
||||
EBIT;01.01.2014;4,7
|
||||
EBIT;01.01.2015;3,6
|
||||
EBIT;01.01.2016;3,1
|
||||
EBIT;01.01.2017;3,1
|
||||
EBIT;01.01.2018;2,99
|
||||
EBIT;01.01.2019;3,22
|
||||
EBIT;01.01.2020;3,78
|
||||
EBIT;01.01.2021;4,72
|
||||
EBIT;01.01.2022;5,2
|
||||
EBITDA;01.01.2018;4,84
|
||||
EBITDA;01.01.2019;5,558
|
||||
EBITDA;01.01.2020;6,905
|
||||
EBITDA;01.01.2021;7,889
|
||||
EBITDA;01.01.2022;8,059
|
|
@ -1,42 +0,0 @@
|
||||
Metrik;Datum;Summe [Milliarden €]
|
||||
Umsatz;01.01.2005;59,6
|
||||
Umsatz;01.01.2006;61,3
|
||||
Umsatz;01.01.2007;62,5
|
||||
Umsatz;01.01.2008;61,7
|
||||
Umsatz;01.01.2009;64,6
|
||||
Umsatz;01.01.2010;62,42
|
||||
Umsatz;01.01.2011;58,65
|
||||
Umsatz;01.01.2012;58,17
|
||||
Umsatz;01.01.2013;60,13
|
||||
Umsatz;01.01.2014;62,66
|
||||
Umsatz;01.01.2015;69,23
|
||||
Umsatz;01.01.2016;73,1
|
||||
Umsatz;01.01.2017;74,95
|
||||
Umsatz;01.01.2018;75,66
|
||||
Umsatz;01.01.2019;80,53
|
||||
Umsatz;01.01.2020;99,95
|
||||
Umsatz;01.01.2021;107,61
|
||||
Umsatz;01.01.2022;114,2
|
||||
EBIT;01.01.2005;7,6
|
||||
EBIT;01.01.2006;5,3
|
||||
EBIT;01.01.2007;5,3
|
||||
EBIT;01.01.2008;7
|
||||
EBIT;01.01.2009;6
|
||||
EBIT;01.01.2010;5,51
|
||||
EBIT;01.01.2011;5,56
|
||||
EBIT;01.01.2012;-3,96
|
||||
EBIT;01.01.2013;4,93
|
||||
EBIT;01.01.2014;7,25
|
||||
EBIT;01.01.2015;7,03
|
||||
EBIT;01.01.2016;9,16
|
||||
EBIT;01.01.2017;9,38
|
||||
EBIT;01.01.2018;8
|
||||
EBIT;01.01.2019;9,46
|
||||
EBIT;01.01.2020;12,37
|
||||
EBIT;01.01.2021;12,58
|
||||
EBIT;01.01.2022;15,41
|
||||
EBITDA;01.01.2018;23,333
|
||||
EBITDA;01.01.2019;24,731
|
||||
EBITDA;01.01.2020;35,017
|
||||
EBITDA;01.01.2021;37,33
|
||||
EBITDA;01.01.2022;40,208
|
|
@ -1,20 +0,0 @@
|
||||
Mohammed;Klein
|
||||
Myriam;Koch
|
||||
Dorothe;Zerusedemeiner
|
||||
Emine;Puviplau
|
||||
Galina;Tosewede
|
||||
Hans-Walter;M<>didostein
|
||||
Ludmilla;Krause
|
||||
Jessica;Lesibedemeiner
|
||||
Franz;Lowufohein
|
||||
Krzysztof;Gaselatem<65>ller
|
||||
Gerolf;Navusedeson
|
||||
Sibylla;Sutedihein
|
||||
Nina;Golebede
|
||||
Alicja;Revibodomeiner
|
||||
Meryem;Kadeduhein
|
||||
Janina;Zimmermann
|
||||
Hendrik;Kr<4B>ger
|
||||
Oskar;Podadi
|
||||
Maria-Luise;Nelaflodeson
|
||||
Nadine;Niwogatemeiner
|
|
@ -1,19 +0,0 @@
|
||||
Company_HR;Company_Court;Jahr;Umsatz;Ebit;EBITDA
|
||||
;12336;5;2005;59600;7600;
|
||||
;12336;5;2006;61300;5300;
|
||||
;12336;5;2007;62500;5300;
|
||||
;12336;5;2008;61700;7000;
|
||||
;12336;5;2009;64600;6000;
|
||||
;12336;5;2010;62420;5510;
|
||||
;12336;5;2011;58650;5560;
|
||||
;12336;5;2012;58170;-3960;
|
||||
;12336;5;2013;60130;4930;
|
||||
;12336;5;2014;62660;7250;
|
||||
;12336;5;2015;69230;7030;
|
||||
;12336;5;2016;73100;9160;
|
||||
;12336;5;2017;74950;9380;
|
||||
;12336;5;2018;75660;8000;23333
|
||||
;12336;5;2019;80530;9460;24731
|
||||
;12336;5;2020;99950;12370;35017
|
||||
;12336;5;2021;107610;12580;37330
|
||||
;12336;5;2022;114200;15410;40208
|
|
Before Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 100 KiB |