ovidens
Analyse-AppsPipeline

SQL-Knoten

Ein SQL-Knoten ist ein Schritt, der Ihre Daten transformiert. Er liest die Ausgabe früherer Knoten und formt sie zu etwas Neuem um, zum Beispiel indem er zwei Tabellen kombiniert, Zeilen filtert oder eine Summe berechnet. SQL ist die Standardsprache für die Arbeit mit Daten, und ein SQL-Knoten verwendet eine Abfrage, die aus den einspeisenden Knoten liest.

Sie müssen kein SQL beherrschen

Das ist der wichtige Teil: Sie müssen SQL nicht selbst schreiben. Beschreiben Sie die gewünschte Transformation in einfacher Sprache, zum Beispiel „behalte nur die Bestellungen dieses Jahres und summiere den Umsatz pro Kunde", und Vera schreibt die Abfrage für Sie. Vera ist der No-Code-Weg; diese Seite erläutert den Knoten für den Fall, dass Sie lesen oder anpassen möchten, was Vera erzeugt hat. Siehe Mit Vera erstellen.

Arbeiten in einem SQL-Knoten

Wenn Sie doch direkt mit der Abfrage arbeiten möchten:

  1. Öffnen Sie im Editor den SQL-Knoten.
  2. Schreiben oder passen Sie die Abfrage an. Sie liest aus den Knoten, die mit diesem verbunden sind.
  3. Führen Sie die Abfrage aus, um ihre Ausgabe und die von ihr erzeugten Spalten zu sehen.

Die Ergebnisse eines SQL-Knotens speisen alle nachgeschalteten Knoten sowie Ihre Visualisierungs-Widgets. Da nachgelagerte Schritte von der Ausgabe dieses Knotens abhängen, verfügen sie erst dann über frische Daten, wenn die Pipeline erfolgreich ausgeführt wurde. Wenn die Abfrage noch nicht ausgeführt wurde, haben Knoten, die auf sie angewiesen sind, keine Daten zum Arbeiten, bis Sie auf Ausführen klicken.

Eine Abfrage in einem SQL-Knoten auszuführen ist eine eigene Berechtigung, getrennt vom Lesen der App. Sie gehört zu den Rollen Mitwirkender, Analyst, App-Ersteller und Admin für den gesamten Workspace - eine Rolle für einen einzelnen Bereich oder eine App gibt sie nicht -, und in Ihrem eigenen persönlichen Bereich haben Sie sie immer. Ohne sie zeigt der Knoten seine Abfrage ohne Schaltfläche Ausführen und mit einem kurzen Hinweis, warum. Konnte die App nicht prüfen, ob Sie sie haben, sagt der Hinweis das stattdessen; laden Sie die Seite neu, um es erneut zu versuchen.

Was die Schaltfläche Ausführen lesen kann

Eine Abfrage, die Sie im Editor ausführen, liest nur die eigenen Knoten dieser App, direkt über ihre ID benannt - dieselbe Regel, die auch der SQL-Editor und das SQL-Widget befolgen. Eine Abfrage darf einen Knoten benennen oder eine WITH-Klausel, die sie selbst definiert, und sonst nichts.

Ein Indikatordaten- oder Analyse-App-Daten-Knoten kann gelesen werden, sobald die Pipeline gelaufen ist: Die Abfrage liest die Kopie seiner Zeilen, die dieser Lauf angelegt hat. Bevor die App einen Lauf hat, gibt es diese Kopie nicht, und der Name wird abgelehnt wie jeder andere Name, hinter dem nichts steht. Eine lokale Entwicklungsumgebung bietet diese beiden Knotentypen einer Abfrage nie an und lehnt ihre Namen ab; lesen Sie einen solchen Knoten dort über einen SQL-Knoten, der aus ihm liest.

Folgendes wird abgelehnt, bevor etwas ausgeführt wird, mit einer Meldung, was zu ändern ist:

  • ein Name mit Präfix, etwa other_app.orders oder main.orders - schreiben Sie orders;
  • ein Name, der kein Knoten dieser App ist, etwa die Tabelle einer anderen App, eine Systemtabelle wie duckdb_tables oder ein Dateipfad;
  • ein Knoten, dessen ID zugleich der Name einer Katalogtabelle der Datenbank ist, etwa duckdb_tables, pg_class oder sqlite_master - benennen Sie den Knoten um, um ihn zu lesen;
  • eine Tabellenfunktion in einer FROM-Klausel, etwa read_parquet(...), range(...) oder unnest(...) - unnest(...) in der SELECT-Liste ist erlaubt;
  • DESCRIBE, SHOW oder SUMMARIZE als Unterabfrage, PIVOT und UNPIVOT, das Lesen einer früheren Version mit AT (VERSION => ...), eine WITH ... AS MATERIALIZED-Klausel und der interne Zustand eines Aggregats mit EXPORT_STATE;
  • eine Funktion, die Einstellungen, Sitzungsangaben oder den Datenbankkatalog liest, als Text übergebenes SQL ausführt oder etwas verändert - zum Beispiel current_setting(...), current_database(), json_serialize_plan(...) oder nextval(...). Die üblichen Funktionen für Text, Zahlen, Datumswerte, Listen und JSON, Aggregate und Fensterfunktionen funktionieren alle. Eine Funktion, die hinter einem Wert steht, wie in name.upper(), wird ebenfalls abgelehnt - schreiben Sie upper(name);
  • ein Typ, der zu einem Schema gehört, etwa CAST(x AS other_app.mood), oder der kein eingebauter DuckDB-Typ ist;
  • eine Zahl, die zu groß ist, als dass die Datenbank sie darstellen könnte, etwa 1e400 - die Abfrage kann nicht geprüft werden und wird daher nicht ausgeführt.

Die SQL-Schlüsselwörter, die ohne Klammern geschrieben werden - current_user, current_schema, current_date und ähnliche - funktionieren weiterhin, auch als Spaltennamen. Sie melden nur die eigene Verbindung dieser Abfrage, nie eine andere App.

Ein Pipeline-Lauf und die Live-Vorschau eines Knotens wenden dieselbe Regel auf seine gespeicherte Abfrage an. Eine Abfrage mit einer dieser Formen lässt sich speichern, doch beim Lauf der Pipeline schlägt dieser Knoten mit derselben Meldung fehl, und die Knoten, die aus ihm lesen, werden übersprungen. Schreiben Sie sie ohne diese Formen um - etwa mit einem bedingten sum(CASE WHEN ...) statt eines PIVOT oder mit SELECT unnest(range(10)) AS n statt FROM range(10). Um Daten einer anderen App zu verwenden, fügen Sie einen Analyse-App-Daten-Knoten hinzu und lesen diesen Knoten über seine ID.

Wie viel eine Ergebnisseite enthalten kann

Die Ergebnisse einer Abfrage werden Seite für Seite angezeigt, zusammen mit der Anzahl aller Zeilen, die die Abfrage geliefert hat. Eine Seite darf höchstens 4 MB Daten und höchstens 262.144 Werte enthalten. Ein Wert wird so gemessen, wie er als Text angezeigt würde; ein langer Text, eine große Liste oder ein in einen anderen Wert verschachtelter Wert zählt also vollständig. Und jedes Element einer Liste, jedes Feld eines Structs sowie jeder Schlüssel und jeder Wert einer Map zählt als eigener Wert.

Eine Abfrage, deren Seite über einer der beiden Grenzen liegt, wird mit einer entsprechenden Meldung abgelehnt. Nichts wird gekürzt: Sie sehen nie einen Teil eines Werts oder nur einige der Zeilen, dargestellt, als wäre es das ganze Ergebnis. So bringen Sie die Seite unter die Grenzen:

  • wählen Sie weniger oder kürzere Spalten aus - für einen langen Text liefert left(text, 1000) seine ersten 1.000 Zeichen und length(text) seine Länge, und len(liste) die Länge einer langen Liste;
  • filtern Sie mit einer WHERE-Klausel auf weniger Zeilen.

Einige Spaltentypen können überhaupt nicht als Abfrageergebnis angezeigt werden: eine UNION, eine VARIANT und ein ARRAY fester Größe, allein oder in einer Liste, einem Struct oder einer Map. Eine Abfrage, die eine solche Spalte liefert, wird mit einer Meldung abgelehnt, die die Spalte nennt. Wandeln Sie sie in der Abfrage um - CAST(... AS VARCHAR) zeigt ihren Wert als Text, und CAST(... AS INTEGER[]) macht aus einem Array fester Größe eine Liste.

Die Grenzen gelten überall, wo die Ergebnisse einer Abfrage sofort angezeigt werden: bei der Schaltfläche Ausführen, im SQL-Editor, in einem SQL-Widget, bei den KI-Werkzeugen, die eine App abfragen, und in der unten beschriebenen Vorschau eines SQL-Knotens. Sie begrenzen, was eine Seite enthält, nicht, wie viele Zeilen eine Abfrage liefern darf.

Sehen, was eine Abfrage liefert, bevor Sie ausführen

Sie müssen die Pipeline nicht ausführen, um zu sehen, ob eine Abfrage stimmt. Öffnen Sie den Tab Daten eines SQL-Knotens, wenn es keine Ausführung zu zeigen gibt, und er zeigt eine Vorschau der AKTUELLEN Abfrage des Knotens über den AKTUELLEN Inhalt der Datasets der App - sofort. Ein Streifen über den Zeilen sagt das ausdrücklich, denn dies sind keine Ausführungsergebnisse: niemand sonst sieht sie, Ihre Visualisierung verwendet sie nicht, und sie ändern sich, sobald Sie die Abfrage oder die Daten bearbeiten.

Das macht die gewöhnliche Schleife kurz. Abfrage bearbeiten, Zeilen ansehen, korrigieren, wieder ansehen - und erst auf Ausführen klicken, wenn es stimmt. Tippen Sie einen Wert in die Tabelle eines Datasets, spiegelt die nächste Vorschau ihn bereits wider.

Einiges dazu sollten Sie wissen:

  • Sie ist für Personen, die die App bearbeiten dürfen. Wer nur liest, sieht wie bisher die Ausführungsergebnisse.
  • Sie zeigt die erste Seite, in der Reihenfolge der Abfrage selbst. Sortieren, Filtern und das Suchfeld werden hier nicht angeboten - eine Vorschau, die eine Sortierung stillschweigend ignoriert, wäre schlechter als eine, die sie gar nicht anbietet. Führen Sie die Pipeline aus, um die vollständige Tabelle zu erhalten.
  • Die Spalten stammen aus dem, was die Abfrage tatsächlich liefert, nicht aus der Liste der Ausgabespalten - eine gerade umgeschriebene Abfrage zeigt ihre neuen Spalten also sofort.
  • Wenn die Abfrage nicht laufen kann, sagt sie warum. Die Meldung nennt die Relation, die sich nicht auflösen ließ; das ist meist ein Tippfehler oder ein fehlender Eintrag in manifest.yml (siehe unten).

Was eine Vorschau lesen kann

Eine Vorschau bindet jeden Dataset-Knoten der App, genau wie eine Ausführung - eine Abfrage, die ein Dataset liest, funktioniert also unabhängig davon, ob manifest.yml es erwähnt.

Die SQL-Knoten, die sie bindet, sind die, die Ihre manifest.yml deklariert, und deren Eingaben wiederum. Eine Abfrage, die die Ausgabe eines ANDEREN SQL-Knotens liest, ohne diesen Knoten in manifest.yml aufzuführen, lässt sich daher nicht in der Vorschau anzeigen, und die Meldung nennt ihn. Nehmen Sie ihn in input_tables auf, und die Vorschau funktioniert - was ohnehin sinnvoll ist, denn dieser Eintrag zeichnet auch den Pfeil auf der Arbeitsfläche und sagt der Pipeline, in welcher Reihenfolge die beiden Schritte laufen.

Zwei Arten von Eingaben lassen sich überhaupt nicht in der Vorschau anzeigen, und die Meldung sagt das, statt wie eine kaputte Abfrage auszusehen: ein Analytics-Daten-Import und eine Indikatordaten-Brücke. Ihre Zeilen werden beim Ausführen der Pipeline geholt, es gibt also nichts Aktuelles zu lesen. Führen Sie die Pipeline aus, um einen Knoten zu sehen, der von einer solchen Eingabe abhängt.

manifest.yml muss zur Abfrage passen

In manifest.yml deklariert ein SQL-Knoten, welche anderen Knoten er liest. Diese Liste ist keine Formalität: Sie ist das Einzige, was die Pfeile auf der Arbeitsfläche zeichnet, und das Einzige, was einer Ausführung sagt, welcher Schritt vor diesem fertig sein muss. Eine Abfrage, die einen Knoten liest, den die Liste nicht nennt, läuft zwar - aber das Bild, das die App von sich selbst hat, ist dann falsch, und zwei Schritte, die in einer bestimmten Reihenfolge laufen müssen, dürfen in der falschen laufen.

Beim Speichern eines SQL-Knotens werden die beiden daher gegeneinander geprüft. Stimmen sie nicht überein, wird das Speichern abgelehnt, und die Meldung nennt den Knoten und die Tabelle:

  • Die Abfrage liest einen Knoten, den input_tables nicht auflistet. Nehmen Sie ihn auf.
  • input_tables nennt einen Knoten, den die Abfrage nie liest. Entfernen Sie ihn, oder lesen Sie ihn in der Abfrage.
  • input_tables nennt etwas, das kein Knoten dieser App ist. Meist ein Tippfehler in der ID.

Ein Knoten, der keinen anderen Knoten liest, braucht keine Liste; eine leere manifest.yml ist für ihn richtig.

Wenn Sie Apps über Vera oder einen KI-Connector bauen, ist das bereits erledigt: Die Werkzeuge verlangen die Liste und kennen dieselbe Regel, sodass die Pfeile von der ersten Version an da sind und nicht erst, nachdem Sie danach fragen.

Die Zeilen-ID eines Datasets lesen

Die Tabelle jedes Dataset-Knotens führt hinter Ihren eigenen Spalten drei weitere:

SpalteBedeutung
_row_idDie stabile ID der Zeile - dieselbe, die auch das Datenraster verwendet.
_created_atWann die Zeile angelegt wurde.
_updated_atWann die Zeile zuletzt geändert wurde.

Sie stehen NACH jeder vom Dataset deklarierten Spalte, in der von Ihnen deklarierten Reihenfolge, und sie können niemals mit einer Ihrer eigenen Spalten kollidieren: ein von Ihnen vergebener Spaltenname beginnt immer mit einem Buchstaben.

SELECT * FROM orders liefert sie neben Ihren Spalten mit. Zu Ausgabespalten des Knotens werden sie aber nicht - die Liste Ausgabespalten eines SQL-Knotens übergeht sie, eine Abfrage mit _row_id speichert und läuft also genau wie eine ohne.

Die Zeilen-ID erlaubt es, eine Zeile mit einer Aussage ÜBER diese Zeile zu verbinden - am nützlichsten mit den Validierungsergebnissen. Der Validierungsknoten heißt normalerweise validation_errors; in einer App, in der einer Ihrer eigenen Knoten diesen Namen bereits hält, erhält er stattdessen eine nummerierte Variante - verwenden Sie also den Namen, den Ihre App tatsächlich anzeigt:

orders_with_findings.sql
SELECT o.*, e.validation_error
  FROM orders o
  LEFT JOIN validation_errors e
    ON e.dataset_technical_id = 'orders'
   AND e.row_id = o._row_id

Sie stehen überall zur Verfügung, wo Sie SQL gegen die App schreiben - im Skript eines SQL-Knotens und im Ad-hoc-Abfragefeld -, dieselbe Abfrage funktioniert also an beiden Stellen.

Ein Dataset ohne Zeilen besitzt die Spalten trotzdem, eine Abfrage darauf liefert also keine Zeilen statt zu scheitern. Zeilen, die vor der Einführung der Zeilen-ID hochgeladen wurden, lesen sich als leer: eine erfundene ID, die stabil aussieht, wäre schlechter als gar keine.

Jede von der Abfrage gelieferte Spalte braucht einen brauchbaren Namen

Der Bezeichner einer Spalte stammt direkt aus der Abfrage, daher muss die Abfrage jeder Spalte einen Namen geben, der als Bezeichner taugt: Kleinbuchstaben, Ziffern und Unterstriche, beginnend mit einem Buchstaben, maximal 32 Zeichen. order_id, revenue und region_2024 sind alle in Ordnung.

Die meisten Abfragen erfüllen das bereits, denn eine ausgewählte Spalte behält ihren Namen. Was das nicht tut, ist ein Ausdruck ohne eigenen Namen. SELECT count(*) liefert eine Spalte, die wörtlich count_star() heißt, und SELECT a + b eine namens (a + b). Vergeben Sie dafür einen Alias:

SELECT count(*) AS order_count

Das Speichern eines Knotens, dessen Abfrage einen unbrauchbaren Namen liefert, wird abgelehnt, und die Meldung nennt die betroffene Spalte. Meist sehen Sie es schon früher: Sobald Sie die Abfrage ausführen, nennt eine Zeile über den Ergebnissen die Spalten, die einen Alias brauchen.

Der Alias lohnt sich ohnehin, nicht nur wegen der Regel. Nachgelagerte Knoten und Ihre Visualisierungs-Widgets sprechen diese Spalte über den NAMEN an - order_count können Sie lesen und referenzieren, count_star() nicht. Ihn zu vergeben kostet nichts: Sie benennen damit die Spalte, die Sie ohnehin gemeint haben.

War diese Seite hilfreich?

Auf dieser Seite