Vor Kurzem schrieb ich davon, wie Human-Computer Interaction (HCI) unsere Art und Weise, wie wir mit Computern interagieren, ändert – und sprang dann in eine Nische meines Herzensthemas Business Intelligence: dem ETL (Extract, Transform, Load).
Auf dieser Reise habe ich euch berichtet, dass das ETL in so einer Art kleiner Krise steckt. Wo bis vor fünf Jahren grafisch basierte Low-Code-Ansätze dominierten, kehrt man aus vielfältigen Gründen nun zurück in echtes Coding. Absoluter Change-Horror für unseren inneren Elefanten.
Probieren wir doch mal aus, ob uns das LLM (Large Language Model) retten kann …
Die Demo
Ich bekomme CSV-Dateien mit Informationen von einer Photovoltaik-Anlage. Darin enthalten ist eine Dimension: Zeit. Die Daten sind Aggregate im Abstand von ca. 5 Minuten. Erste kleine Gemeinheit: technologiebedingt können es auch mal 5:01 Minuten sein oder 5:03 Minuten.
Dazu gibt es eine Reihe von Fakten wie den Ertrag, die Netzeinspeisung usw., jeweils in Kilowatt angegeben als Aggregat für dieses „ca. 5-Minuten“-Intervall.


Versuch 1: Eine textuelle Beschreibung für ein einfaches Importieren
Das LLM bekommt eine CSV-Datei mit den oben genannten Inhalten und folgende Beschreibung:
| Ich möchte, dass du ein Python-Skript schreibst:
– Lese eine oder mehrere CSV-Dateien mit diesem Format und Inhalt – Schreibe die Inhalte 1:1 in eine MariaDB-Tabelle namens – Bitte erzeuge auch ein DDL mit den Create-Befehlen – Nach Abarbeitung einer Datei, schiebe sie in den Unterordner – Vermeide Leerzeichen in Spaltennamen und füge eine Spalte mit dem Dateinamen hinzu, aus dem die jeweilige Zeile kommt – Die Datenbank erreichst du über |
Was hat funktioniert?
- Ich bekomme ein lauffähiges Python-Skript.
- Ich kann den Pfad als Parameter mit angeben.
- Das LLM importiert eine CSV oder iterativ mehrere.
- Es hat meine Anweisungen bezüglich der Daten, des Logins zur Datenbank und der Archivierung der Datei umgesetzt.
Was hat nicht so gut funktioniert?
- Ich habe nicht erfahren, welche Python-Bibliotheken ich noch herunterladen muss.
- Das DDL, um die Tabelle zu erstellen, ist eingebettet. Das brauche ich bei einem regelmäßig laufenden Job nicht. Ein einmaliger DDL-Befehl wäre mir lieber gewesen.
Ganz ehrlich: Zwei Minuten Arbeit und ich habe ein Skript, das ich so laufen lassen kann und das seinen Job macht. Keinen komplexen. Aber es läuft, ist leserlich formatiert und in Funktionen untergliedert.

Die Abstriche sind Nebensache und lassen sich mit einem „Kannst du mir bitte das Create-Skript als .sql einzeln geben?“ lösen. Ich habe hier auch nicht präzise gepromptet.
Allerdings: Während ich dies schreibe, nutze ich das taufrische OpenAI-5.2-Modell. Mit dem 5.0 hat der gleiche Prompt auch die beiden Negativpunkte besser gelöst.
Sei’s drum. Weiter geht’s.
Schaffen wir Fakten
Ja, so einen einfachen Staging-Job zum Import von Hand zu schreiben ist nervig, aber das kann man heute auch super generisch erledigen. Als Data-Lakehouse-Betreiber hat man sein Ingestion-Framework, welches das ziemlich schnell erledigen sollte, parat. Da braucht’s die KI im Grunde nicht.
Gehen wir einen Schritt weiter und erzeugen echte Kennzahlen.
Mein Prompt:
| Ich möchte außerdem, dass du eine View v_fkt_pv anlegst, die auf der stage_pv basiert und neben den gegebenen Spalten zusätzlich eine Umrechnung in Kilowattstunden anbietest sowie die Autarkie pro Zeile.
Ich möchte, dass du eine fkt_pv anlegst, die den Output der View persistiert und mit jedem Ladelauf aktuell gehalten wird. Ich möchte, dass du eine fkt_pv_agg anlegst, die eine Aggregation der Einzelwerte auf Tagesbasis vornimmt. |
Ich beschreibe also relativ präzise, wie er die Faktenschicht bauen soll, nämlich mit einer View als Definition für Transformationen und einer Persistenzschicht. Allerdings verrate ich dem LLM ein paar Dinge NICHT.
So erfährt es
- nichts davon, wie es auf Kilowattstunden kommt,
- nichts davon, dass die Zeilen Aggregate unterschiedlicher Länge beinhalten – was entscheidend ist für eine korrekte Umrechnung in kWh,
- und ich erzähle auch nicht, was ich mit „Autarkie“ meine.
Und siehe da. Es riecht den Braten:
| (s.stromerzeugung_kw * (IFNULL(TIMESTAMPDIFF(SECOND, LAG(s.uhrzeit) OVER (PARTITION BY s.source_filename ORDER BY s.uhrzeit), s.uhrzeit), 300) / 3600.0)) AS stromerzeugung_kwh, |
Statt auf fixe 5-Minuten-Intervalle zu gehen, baut es eine LAG-Funktion in die Abfrage ein und macht es sauber, fragt mich aber gleichzeitig:
| „Wenn du mir kurz sagst, ob deine Daten immer 5-Minuten sind (oder variabel), kann ich dir die kWh-Berechnung noch so anpassen, dass sie: – entweder fix per Parameter läuft (z. B. –interval-seconds 300) – oder robust per LEAD/LAG + Plausibilitätskappung (z. B. max. 15 min, min. 1 min) gerechnet wird.“ |
Das heißt, die KI merkt, dass man hier vereinfachen könnte, wenn die Datenqualität etwas besser wäre.
Auch die Autarkie, also den Anteil am Eigenverbrauch, der über die PV-Anlage abgedeckt wird, berechnet sie korrekt als 1 – (Netzbezug / Stromverbrauch) inkl. 0-Teiler-Absicherung.
Und jetzt die Sternchenaufgabe
Ich gebe der KI den Endgegner: meine Zeichenkunst. Ich fertige ganz im klassischen ETL-Style einen graphischen Datenfluss an und gebe ein paar Stichwörter mit, wie z. B., dass die Quelle eine CSV ist, welche Tabellen ich erwarte und welche KPI.
Der Prompt sieht so aus:
| Ich habe dir eine CSV-Datei mitgegeben. Das ist ein Beispiel für eine tägliche Quellsystemlieferung. Bitte implementiere eine ETL-Strecke, wie im PNG skizziert, für diese CSV. |

Die KI ist nicht intelligent
An dieser Stelle sei erwähnt: Eine KI besitzt natürlich keine echte Intelligenz, auch wenn das „I“ dies suggeriert. Hinter ihr steht ein Algorithmus – ein kompliziertes Matheprogramm, das ausrechnet, wofür man es geschaffen hat. Es sind clevere und komplexe Aufgaben, aber am Ende sind es Matheaufgaben. Das LLM ist in der Lage, einen Text aus einer Datenbank entgegenzunehmen und für jedes Textstück Vektoren abzurufen – dargestellt als Zahlen, die das Wort beschreiben – und dann ähnliche Wörter als Antwort zu finden. Das sind Wörter mit nahegelegenen Vektoren, vereinfacht ausgedrückt. Und diese nahen Wörter nach und nach immer wieder durchgerechnet ergeben dann die Antwort.
Was brauche ich für ein gutes Ergebnis?
Damit ich ein gutes Ergebnis erhalte, kommt es also darauf an, dass
- eine gute OCR-Erkennung vorgeschaltet ist, die meine Handschrift erkennt
- und meine Skizze genug beschreibende Elemente enthält.
Als erstes fällt auf, dass deutlich länger „nachgedacht“ wird als zuvor. Allerdings habe ich nun auch die komplette Anforderung eingekippt, nicht wie zuvor in zwei Teilen. Das LLM suggeriert mir erst mal, es habe verstanden, was ich will:
| „Hier ist eine komplette ETL-Strecke für deine tägliche PV-CSV – exakt nach der Skizze: CSV ? stge_pv (1:1) ? fkt_pv (+ kWh-Spalten + Autarkie) ? fkt_pv_agg (Tages-SUM je Typ)“ |
Das heißt, die OCR-Erkennung scheint funktioniert zu haben. Mehr lässt sich daraus zunächst nicht ableiten. Offensichtlich ist die 1:1-Wiedergabe dessen, was ich möchte, in einem Vektorraum mit nahe beieinanderliegenden Repräsentationen noch kein Ausdruck von tatsächlichem Verständnis. Übrigens ein Grund, warum die KI immer so „selbstsicher“ und korrekt wirkt und doch, wenn sie etwas nicht kann, ganz zwangsweise halluziniert (lügt).
Dieses Mal wird mir eine ZIP-Datei angeboten. Das LLM liefert neben dem eigentlichen Code ein docker-compose-File, das eine lokale Datenbank startet, sowie eine README und eine requirements.txt. Im Vergleich zum vorherigen Prompt wählt es damit an einer Stelle, an der ich in beiden Fällen Freiheitsgrade gelassen habe, einen anderen Lösungsweg. Der Prompt war allerdings etwas präziser: „Die Datenbank erreichst du über …“ suggeriert, dass diese bereits existiert. Daher wurde im ersten Versuch kein docker File bereitgestellt, welches eine Datenbank hochfährt. Hier schon, da es keine Aussage gab, ob ich eine Datenbank erstellt haben oder nur ansprechen möchte.
Ich übernehme lediglich den Python-Code und lasse die restlichen Artefakte weg. Wie zuvor führe ich ihn blind aus – ganz im Sinne eines fail-fast-Ansatzes. Und er failt fast: keine Datenbankverbindung. Bei der Analyse stelle ich fest, dass meine handschriftliche Vorlage nicht korrekt erkannt wurde; ich passe den Datenbanknutzer an. Zusätzlich scheint das diesmal verwendete SQLAlchemy Probleme mit der DNS-Namensauflösung zu haben. Statt localhost nutze ich daher 127.0.0.1 – und siehe da: es läuft.
Ich erhalte die Staging-Tabelle (mit dem Namen „stge“) sowie beide gewünschten Faktentabellen. Auch in dieser Version werden alle KPIs korrekt berechnet. Beim Durchlesen des Codes fällt jedoch schnell die veränderte Herangehensweise auf: Während zuvor stark SQL-lastig gearbeitet wurde – was ich durch die View explizit intendiert hatte –, wird die Business-Logik diesmal deutlich näher am Python-Code umgesetzt.
Nachfolgend ein Ausschnitt aus der Berechnung der kWh-Stunden:

Die Faktentabelle mit dem Tagesaggregat sieht diesmal völlig anders aus:

Fachlich ist sie korrekt, aber sie wurde transponiert. Statt einem Attribut je Kennzahl, gibt es eine Spalte für die Metrik und eine beschreibende Spalte. Die Skizze ließ hier einfach mehr Spielraum zur Interpretation des Ergebnisses zu als ein gut formulierter Prompt.
Dennoch: Für eine so lieblos dahingeschmierte Skizze wie meine war das Ergebnis durchaus brauchbar.
Fazit
Ich habe in diesem Beitrag praktisch gezeigt, wie die Theorie des HCI im Sinne von Die Arbeit mit einem Computer ist ähnlicher zur Kommunikation mit einem Gegenüber als dem Nutzen eines Werkzeugs (und mit LLMs erst recht) für eine Nische der Softwareentwicklung aussehen kann.
Der Test mit dem OpenAI-Modell 5.2 war durchaus gut, und in dieser Qualität kann man verwendbaren Code produzieren. Eine fachliche Beschreibung und eine Zeichnung, die das Wesentliche sichtbar macht, müssen als Anforderungsdokumentation ohnehin angefertigt werden. Es ist also denkbar, eine verständlich geschriebene und strukturierte Story als Aufsatzpunkt zum Coden zu nehmen.
Für die angesprochene Nische ETL, die sich aktuell in einem großen Change befindet, könnten LLMs eventuell diese Lücke füllen und eine Hilfestellung für Menschen sein, die sich nun umstellen müssen.
Der zuletzt erzeugte Code ist übrigens inklusive Kommentaren 337 Zeilen lang. Das grafische ETL-Tool Talend, in dem dieselbe Semantik abgebildet wurde, hat hingegen 9.319 Zeilen Java-Code produziert – was einer der Gründe dafür ist, warum diese Tools kritisch betrachtet werden.
Müssen wir nun Sorge um unsere Jobs haben?
Nein. Ohne Verständnis für Datenmodellierung, ETL und Co. würden wir
- nicht verstehen, was da passiert, könnten außerdem nicht debuggen und müssten dem LLM vollends vertrauen.
- könnten wir die Prompts nicht präzise genug schreiben.
- ist das LLM nur so gut wie das Wissen, mit dem es gefüttert wurde.
Es braucht also die Entwickler:innen da draußen, die Lösungen finden, Kennzahlen definieren und Berechnungen implementieren, damit das LLM diese finden und wiedergeben kann. Denn mehr tut es nicht: Es gibt Wissen wieder, das ein Mensch gefunden hat. Die Suche nach dem passenden Wissen wird nur leichter.
Mehr aus dieser Serie lesen?
Diese Reihe lohnt sich für alle Analytics-Expert:innen, die verstehen wollen, wie KI und LLMs unsere tägliche Praxis im BI- und ETL-Umfeld verändern.
- Was haben ein Hammer und ein LLM (nicht) gemeinsam?
In diesem Einstiegsteil geht es um die Grundidee hinter LLMs und Human-Computer Interaction: Warum ein LLM kein Werkzeug im klassischen Sinne ist, wie natürliche Sprache zur neuen Schnittstelle wird und welche Rolle das für die Interaktion mit Systemen spielt.
Hier weiterlesen: Was haben ein Hammer und ein LLM (nicht) gemeinsam? - Vibe Coding im BI-Bereich – Wie KI uns ETL-Entwickler retten kann
Der nächste Beitrag der Serie widmet sich dem Trend Vibe Coding, bei dem KI-gestützte Interaktion die Art verändert, wie Code entsteht und Workflows definiert werden. Er beleuchtet, wie dieser Ansatz für BI-Teams aussehen kann und welche Chancen er für ETL-Entwickler bietet.
Hier weiterlesen: Vibe Coding im BI-Bereich: Wie KI uns ETL-Entwickler retten kann
