Kapitel 1. Abfrage-Fibel

Diese Arbeit wurde mithilfe von KI übersetzt. Wir freuen uns über dein Feedback und deine Kommentare: translation-feedback@oreilly.com

Krempeln wir die Ärmel hoch und schauen uns einige Abfragen an, die die select -Anweisung verwenden, also die SQL-Anweisung, mit der Abfragen ausgeführt werden.

Grundlagen der Abfrage

Wenn du die im Vorwort aufgeführten Schritte befolgt hast, dann hast du ein Snowflake-Konto erstellt und deine Beispieldatenbank angelegt. Um Abfragen mit Snowsight einzugeben, erstellst du ein neues Arbeitsblatt, indem du auf die Schaltfläche Arbeitsblätter auf der linken Seite des Bildschirms klickst und dann auf die Schaltfläche "+" oben rechts. Dein neues Arbeitsblatt erscheint im linken Fenster mit einem Namen, der das aktuelle Datum und die aktuelle Uhrzeit enthält, aber du kannst es umbenennen in Learning_Snowflake_SQL umbenennen, um es für die Beispiele in diesem Buch zu verwenden. Bevor du Abfragen in deinem neuen Arbeitsblatt ausführst, setze das Schema auf das Schema Public in der Learning_SQL-Datenbank: use schema learning_sql.public; .

Nachdem du diesen Befehl in dein Arbeitsblatt eingegeben hast, klicke auf den Pfeil nach rechts oben auf dem Bildschirm, um den Befehl auszuführen, wie in Abbildung 1-1 dargestellt.

Jedes Mal, wenn du dich bei Snowsight anmeldest, solltest du diese use schema Anweisung ausführen, bevor du Abfragen an die Beispieldatenbank stellst.

Abbildung 1-1. Einstellen des Schemas über die Weboberfläche von Snowflake (Snowsight)

Snowflake Web Interface versus SnowSQL CLI

Für die meisten Beispiele in diesem Buch verwende ich das Snowflake CLI, bekannt als SnowSQL, und nicht die Snowsight-Weboberfläche. Auf diese Weise können die SQL-Anweisungen in den Beispielen aus dem Buch kopiert werden (vorausgesetzt, du verwendest ein Online-Exemplar) und es wird auch unnötiger Ballast vermieden. Ich empfehle dir jedoch, Snowsight zu verwenden, da es ein leistungsstarkes Tool ist, das von jedem Gerät aus ausgeführt werden kann. Wenn du jedoch SnowSQL verwenden möchtest, kannst du diese Installations- und Nutzungsanweisungen befolgen.

Wenn du SnowSQL verwendest, füge immer ein Semikolon an das Ende deiner SQL-Anweisung an und drücke dann Enter, um die Anweisung auszuführen. Neben der Einstellung des aktuellen Schemas mit dem Befehl use schema habe ich auch die Eingabeaufforderung in SnowSQL mit der folgenden Anweisung eingestellt:

!set prompt_format=[schema]>;

Aus diesem Grund zeigen alle meine Beispiele die Eingabeaufforderung PUBLIC>, aber du kannst auch das Standardformat der Eingabeaufforderung verwenden, wenn du das bevorzugst.

Als Nächstes wollen wir mit einer einfachen Abfrage beginnen, die das aktuelle Datum liefert:

PUBLIC>select current_date;
+--------------+
| CURRENT_DATE |
|--------------|
| 2023-03-19   |
+--------------+

Diese Abfrage ruft die eingebaute Funktion current_date() auf, die standardmäßig das Datum im Format JJJJ-MM-TT (vierstelliges Jahr, zweistelliger Monat, zweistelliger Tag) zurückgibt. Select-Anweisungen geben eine Ergebnismenge zurück, die aus einer oder mehreren Zeilen mit einer oder mehreren Spalten besteht. In diesem ersten Beispiel besteht die Ergebnismenge aus einer einzigen Zeile mit einer einzigen Spalte.

Eine Datenbanktabelle besteht auch aus einer oder mehreren Zeilen mit einer oder mehreren Spalten, sodass eine Ergebnismenge, die von einer select Anweisung zurückgegeben wird, der gesamte Inhalt einer Tabelle sein kann. So würde das bei der kleinsten Tabelle in der Beispieldatenbank, Region, aussehen, die die folgenden Daten enthält:

PUBLIC>select *
       from region;
+-------------+-------------+------------------------------------+
| R_REGIONKEY | R_NAME      | R_COMMENT                          |
|-------------+-------------|------------------------------------+
|           0 | AFRICA      | lar deposits. blithely final pac...|
|           1 | AMERICA     | hs use ironic, even requests. s    |
|           2 | ASIA        | ges. thinly even pinto beans ca    |
|           3 | EUROPE      | ly final courts cajole furiously...|
|           4 | MIDDLE EAST | uickly special accounts cajole c...|
+-------------+-------------+------------------------------------+

Hier sind ein paar Dinge, die du bei dieser Frage beachten solltest:

  • select * ist eine Abkürzung für "jede Spalte zurückgeben".
  • Diese Abfrage enthält sowohl eine select Klausel als auch eine from Klausel. Die from Klausel wird verwendet, um die Tabelle(n) anzugeben, aus denen Daten abgerufen werden sollen.

Und hier sind ein paar Dinge, die du bei der Ergebnismenge beachten solltest:

  • Die Tabelle Region hat 5 Zeilen und 3 Spalten.
  • Die Kommentare in der dritten Spalte der Ergebnismenge werden zufällig generiert. Das gilt für alle beschreibenden Spalten in der Beispieldatenbank.
  • SnowSQL formatiert die Ergebnismenge automatisch so, dass sie die Spaltennamen enthält, und verwendet die Zeichen +, - und |, um jede Spalte und Zeile zu umrahmen.

Wenn du Snowsight und nicht SnowSQL verwendest, sieht die Ergebnismenge etwa so aus wie in Abbildung 1-2.

Abbildung 1-2. Abfrage der Tabelle Region mit Snowsight

Wenn du sehen möchtest, welche Spalten in einer Tabelle vorhanden sind, kannst du die Anweisung describe von Snowflake verwenden. Für die Tabelle Region gibt sie folgendes zurück:

PUBLIC>describe table region;
+-------------+--------------+--------+-------+---------+...
| name        | type         | kind   | null? | default |...
|-------------+--------------+--------+-------+---------+...
| R_REGIONKEY | NUMBER(38,0) | COLUMN | N     | NULL    |...
| R_NAME      | VARCHAR(25)  | COLUMN | N     | NULL    |...
| R_COMMENT   | VARCHAR(152) | COLUMN | Y     | NULL    |...
+-------------+--------------+--------+-------+---------+...

Die Tabelle Region hat eine numerische Spalte mit dem Namen r_regionkey, die einen eindeutigen numerischen Wert für jede Zeile enthält, und zwei Zeichenspalten (varchar steht für variable Zeichen), die den Namen der Region und Kommentare zu der Region enthalten.

Befehlsparameter

Viele der in Snowflake eingebauten Befehle, wie der im vorherigen Beispiel gezeigte show tables Befehl, enthalten mehrere optionale Parameter, die beeinflussen, wie der Befehl ausgeführt werden soll. In diesem Fall habe ich den Parameter terse verwendet, um festzulegen, dass nur 5 der 18 möglichen Spalten in die Ergebnismenge aufgenommen werden sollen. Wenn du alle Parameter sehen willst, die für die Snowflake-Befehle zur Verfügung stehen, kannst du in der Snowflake SQL-Befehlsreferenz nachsehen.

Um Informationen über alle in einer Datenbank verfügbaren Tabellen zu erhalten, verwende den Befehl show tables (mit der Option terse kannst du die Anzahl der Spalten einschränken):

PUBLIC>show terse tables in PUBLIC;
+-------------------------------+----------+-------+...
| created_on                    | name     | kind  |...
|-------------------------------+----------+-------+...
| 2023-02-28 06:55:21.382 -0800 | CUSTOMER | TABLE |...
| 2023-02-28 06:51:41.226 -0800 | LINEITEM | TABLE |...
| 2023-02-28 06:43:46.739 -0800 | NATION   | TABLE |...
| 2023-02-28 06:53:19.090 -0800 | ORDERS   | TABLE |...
| 2023-02-28 06:44:35.450 -0800 | PART     | TABLE |...
| 2023-02-28 06:45:20.267 -0800 | PARTSUPP | TABLE |...
| 2023-02-28 06:42:32.322 -0800 | REGION   | TABLE |...
| 2023-02-28 06:49:39.242 -0800 | SUPPLIER | TABLE |...
+-------------------------------+----------+-------+...

Eine Sache, die du beachten solltest, ist, dass die Ausgabe von show tables nur Tabellen enthält, für die du die Berechtigung hast, sie zu sehen. Die acht Tabellen, die der Befehl show tables ausgibt, werden für die meisten Beispiele in diesem Buch verwendet. Anhang A zeigt ein Diagramm dieser Tabellen, einschließlich aller Spalten und der Beziehungen zwischen den Tabellen.

Abfrageklauseln

Abfragen bestehen aus mehreren Komponenten, auch Klauseln genannt. Zwei der Klauseln, select und from, wurden im vorigen Abschnitt vorgestellt, aber es gibt acht verschiedene Klauseln, die zu einer Snowflake-Abfrage hinzugefügt werden können, wie in Tabelle 1-1 dargestellt.

Tabelle 1-1. Abfrageklauseln
Name der Klausel Zweck
wähle Gibt die Spalten an, die in die Ergebnismenge aufgenommen werden sollen
von Identifiziert die Tabellen, aus denen Daten abgerufen werden sollen, und wie die Tabellen verbunden werden sollen
wo Entfernt unerwünschte Zeilen aus der Ergebnismenge
Gruppe von Gruppiert Zeilen nach gemeinsamen Werten zusammen
mit Entfernt unerwünschte Zeilen in der Ergebnismenge auf der Grundlage von Gruppierungen
qualifizieren Entfernt unerwünschte Zeilen in der Ergebnismenge basierend auf den Ergebnissen der Fensterfunktionen (siehe Kapitel 14)
Bestellung durch Sortiert die Ergebnismenge nach einer oder mehreren Spalten
Grenze Begrenzt die Anzahl der Zeilen in der Ergebnismenge

Von den acht Klauseln, die in Tabelle 1-1 aufgeführt sind, ist nur select erforderlich, und einige werden zusammen verwendet (z. B. würdest du die Klausel having nicht verwenden, ohne vorher eine Klausel group by anzugeben). Alle diese Klauseln werden in diesem Buch behandelt, wobei einige der fortgeschritteneren Klauseln in späteren Kapiteln behandelt werden. In den folgenden Abschnitten wird die Verwendung der einzelnen Klauseln erläutert.

Die Select-Klausel

Wie bereits im Kapitel gezeigt hat, kann eine Abfrage auch nur aus einer select Klausel bestehen. Hier ist ein Beispiel, das eine Ergebnismenge aus einer einzigen Spalte zurückgibt:

PUBLIC>select 'Welcome to Snowflake SQL!';
+-----------------------------+
| 'WELCOME TO SNOWFLAKE SQL!' |
|-----------------------------|
| Welcome to Snowflake SQL!   |
+-----------------------------+

Die select Klausel ist die einzige erforderliche Klausel in einer Abfrage, aber für sich genommen ist sie nicht besonders nützlich. Um die Sache interessanter zu machen, schreiben wir eine Abfrage, um einige Spalten aus der Tabelle Nation abzurufen, die wie folgt aussieht:

PUBLIC>describe table nation;
+-------------+--------------+--------+-------+---------+...
| name        | type         | kind   | null? | default |...
|-------------+--------------+--------+-------+---------+...
| N_NATIONKEY | NUMBER(38,0) | COLUMN | N     | NULL    |...
| N_NAME      | VARCHAR(25)  | COLUMN | N     | NULL    |...
| N_REGIONKEY | NUMBER(38,0) | COLUMN | N     | NULL    |...
| N_COMMENT   | VARCHAR(152) | COLUMN | Y     | NULL    |...
+-------------+--------------+--------+-------+---------+...

Die nächste Abfrage ruft die ersten drei Spalten von Nation ab:

PUBLIC>select n_nationkey, n_name, n_regionkey
       from nation;
+-------------+----------------+-------------+
| N_NATIONKEY | N_NAME         | N_REGIONKEY |
|-------------+----------------+-------------|
|           0 | ALGERIA        |           0 |
|           1 | ARGENTINA      |           1 |
|           2 | BRAZIL         |           1 |
|           3 | CANADA         |           1 |
|           4 | EGYPT          |           4 |
|           5 | ETHIOPIA       |           0 |
|           6 | FRANCE         |           3 |
|           7 | GERMANY        |           3 |
|           8 | INDIA          |           2 |
|           9 | INDONESIA      |           2 |
|          10 | IRAN           |           4 |
|          11 | IRAQ           |           4 |
|          12 | JAPAN          |           2 |
|          13 | JORDAN         |           4 |
|          14 | KENYA          |           0 |
|          15 | MOROCCO        |           0 |
|          16 | MOZAMBIQUE     |           0 |
|          17 | PERU           |           1 |
|          18 | CHINA          |           2 |
|          19 | ROMANIA        |           3 |
|          20 | SAUDI ARABIA   |           4 |
|          21 | VIETNAM        |           2 |
|          22 | RUSSIA         |           3 |
|          23 | UNITED KINGDOM |           3 |
|          24 | UNITED STATES  |           1 |
+-------------+----------------+-------------+

Es gibt vier Spalten in der Tabelle Nation, aber die Abfrage ruft nur drei davon ab. Der Zweck der select Klausel in dieser Abfrage besteht also darin, anzugeben, welche der möglichen Spalten in die Ergebnismenge aufgenommen werden sollen. Eine select Klausel ist jedoch nicht nur auf die Spalten in einer Tabelle beschränkt, sondern kann jede der folgenden Spalten enthalten:

  • Literale, wie zum Beispiel die Zahl 99 oder die Zeichenkette 'Welcome to Snowflake SQL!'
  • Ausdrücke, wie zum Beispiel n_nationkey * 100
  • Eingebaute Funktionsaufrufe, wie z.B. concat(n_nationkey, ' : ', n_name)
  • Benutzerdefinierte Funktionsaufrufe, die mit Java, Python, JavaScript oder der Snowflake Scripting-Sprache erstellt wurden

Eingebaute und benutzerdefinierte Funktionen werden in späteren Kapiteln im Detail behandelt.

Spalten-Aliase

Auch wenn der Datenbankserver die Spaltennamen für dich vergibt, kannst du deine eigenen Namen mit Hilfe von Spaltenaliasen angeben. Dies ist besonders hilfreich für alle Literale, Ausdrücke oder Funktionsaufrufe, die in deiner select Klausel enthalten sind. Hier ist ein Beispiel, bei dem die Spaltenaliase fett gedruckt sind:

PUBLIC>select 'Welcome to Snowflake SQL!' as welcome_message,
         5 * 3.1415927 as circle_circumference,
         dayname(current_date) as day_of_week;
+---------------------------+----------------------+-------------+
| WELCOME_MESSAGE           | CIRCLE_CIRCUMFERENCE | DAY_OF_WEEK |
|---------------------------+----------------------+-------------|
| Welcome to Snowflake SQL! |           15.7079635 | Fri         |
+---------------------------+----------------------+-------------+

Den Spaltenaliasen kann das Schlüsselwort as vorangestellt werden, was die Lesbarkeit verbessert.

Duplikate entfernen

In manchen Fällen kann eine Abfrage doppelte Werte zurückgeben. Zum Beispiel gibt die folgende Abfrage die Werte in der Spalte n_regionkey der Tabelle Nation zurück:

PUBLIC>select n_regionkey from nation;
+-------------+
| N_REGIONKEY |
|-------------|
|           0 |
|           1 |
|           1 |
|           1 |
|           4 |
|           0 |
|           3 |
|           3 |
|           2 |
|           2 |
|           4 |
|           4 |
|           2 |
|           4 |
|           0 |
|           0 |
|           0 |
|           1 |
|           2 |
|           3 |
|           4 |
|           2 |
|           3 |
|           3 |
|           1 |
+-------------+

Wie du sehen kannst, gibt es in den 25 Zeilen der Tabelle Nation nur fünf verschiedene Werte für n_regionkey. Wenn du nur die eindeutigen Werte in der Spalte n_regionkey abrufen möchtest, kannst du das Schlüsselwort distinct verwenden:

PUBLIC>select distinct n_regionkey from nation;
+-------------+
| N_REGIONKEY |
|-------------|
|           0 |
|           1 |
|           3 |
|           2 |
|           4 |
+-------------+

Wenn du distinct zu deiner select Klausel hinzufügst, weist du den Server an, die Werte zu sortieren und alle Duplikate zu entfernen.

Die Von-Klausel

Früher in diesem Kapitel haben die Beispiele Daten aus einer einzigen Tabelle abgerufen, aber die from Klausel kann auf mehrere Tabellen verweisen. Wenn zwei oder mehr Tabellen in der from Klausel enthalten sind, erweitert sich ihre Rolle, da sie nicht nur eine Liste von Tabellen enthält, sondern auch die Art und Weise, wie die Tabellen verknüpft werden sollen. Zur Veranschaulichung: Angenommen, du möchtest Daten aus der Tabelle Nation abrufen, aber anstatt die Spalte n_regionkey abzurufen, möchtest du den Wert n_regionkey verwenden, um den Namen der Region aus der Tabelle Region abzurufen. So würde die Abfrage aussehen:

PUBLIC>select n_nationkey, n_name as nation_name, 
         r_name as region_name
       from nation join region
       on nation.n_regionkey = region.r_regionkey;
+-------------+----------------+-------------+
| N_NATIONKEY | NATION_NAME    | REGION_NAME |
|-------------+----------------+-------------|
|           0 | ALGERIA        | AFRICA      |
|           1 | ARGENTINA      | AMERICA     |
|           2 | BRAZIL         | AMERICA     |
|           3 | CANADA         | AMERICA     |
|           4 | EGYPT          | MIDDLE EAST |
|           5 | ETHIOPIA       | AFRICA      |
|           6 | FRANCE         | EUROPE      |
|           7 | GERMANY        | EUROPE      |
|           8 | INDIA          | ASIA        |
|           9 | INDONESIA      | ASIA        |
|          10 | IRAN           | MIDDLE EAST |
|          11 | IRAQ           | MIDDLE EAST |
|          12 | JAPAN          | ASIA        |
|          13 | JORDAN         | MIDDLE EAST |
|          14 | KENYA          | AFRICA      |
|          15 | MOROCCO        | AFRICA      |
|          16 | MOZAMBIQUE     | AFRICA      |
|          17 | PERU           | AMERICA     |
|          18 | CHINA          | ASIA        |
|          19 | ROMANIA        | EUROPE      |
|          20 | SAUDI ARABIA   | MIDDLE EAST |
|          21 | VIETNAM        | ASIA        |
|          22 | RUSSIA         | EUROPE      |
|          23 | UNITED KINGDOM | EUROPE      |
|          24 | UNITED STATES  | AMERICA     |
+-------------+----------------+-------------+

Die from Klausel enthält zwei Tabellen, Nation und Region, und enthält auch die on Subklausel, um anzugeben, dass die regionkey Spalten (n_regionkey in der Nation Tabelle und r_regionkey in der Region Tabelle) verwendet werden sollen, um die Tabellen zu verbinden. Einfacher ausgedrückt: Die Abfrage gibt an, dass für jede Zeile in der Tabelle Nation der Wert n_regionkey verwendet wird, um den Namen der Region in der Tabelle Region nachzuschlagen. Multitable Joins werden in Kapitel 3 ausführlich behandelt.

Die Wo-Klausel

Es gibt zwar Fälle, in denen du alle Zeilen aus einer Tabelle abrufen möchtest, aber es ist üblich, nur eine Teilmenge der Zeilen abzurufen, was die Aufgabe der where Klausel ist. Du möchtest zum Beispiel nur die Zeilen aus der Tabelle Nation abrufen, deren Name mit dem Buchstaben U beginnt:

PUBLIC>select n_name
       from nation
       where n_name like 'U%';
+----------------+
| N_NAME         |
|----------------|
| UNITED KINGDOM |
| UNITED STATES  |
+----------------+

Die Aufgabe der where Klausel ist das Filtern, also das Entfernen unerwünschter Zeilen. Jedes Element in der where Klausel wird als Bedingung bezeichnet, was für das vorherige Beispiel ist:

n_name like 'U%'

Es kann mehrere Bedingungen in einer where Klausel geben, wie das nächste Beispiel zeigt, das die Namen der Nationen abfragt, die entweder mit U oder A beginnen:

PUBLIC>select n_name
       from nation
       where n_name like 'U%'
         or n_name like 'A%';
+----------------+
| N_NAME         |
|----------------|
| ALGERIA        |
| ARGENTINA      |
| UNITED KINGDOM |
| UNITED STATES  |
+----------------+

Die vorherige Abfrage enthält zwei Bedingungen, die durch or getrennt sind. Damit wird festgelegt, dass jede Zeile, die eine der beiden Bedingungen erfüllt, in die Ergebnismenge aufgenommen werden soll. Kapitel 2 behandelt das Filtern im Detail.

Die Gruppe nach Klausel

Wie der Name schon sagt, wird die group by Klausel zur Gruppierung von Zeilen verwendet. Die Gruppierung von Datenzeilen ist eine sehr gängige Praxis, insbesondere für Berichte und Datenanalysen. Zur Veranschaulichung zählt das folgende Beispiel die Anzahl der Länder in der Tabelle Nation für jede Zeile in der Tabelle Region:

PUBLIC>select r_name as region_name,
         count(*) as number_of_countries
       from nation join region
       on nation.n_regionkey = region.r_regionkey
       group by r_name;
+-------------+---------------------+
| REGION_NAME | NUMBER_OF_COUNTRIES |
|-------------+---------------------|
| AFRICA      |                   5 |
| AMERICA     |                   5 |
| MIDDLE EAST |                   5 |
| EUROPE      |                   5 |
| ASIA        |                   5 |
+-------------+---------------------+

Diese Abfrage gruppiert die Zeilen in Nation nach ihren Regionen und verwendet dann die eingebaute Funktion count(), um die Anzahl der Nationen in jeder Region zu ermitteln. Kapitel 7 behandelt die Gruppierung.

Die Besitzstandsklausel

Ich habe das Konzept der Filterung vorgestellt, als die Rolle der where Klausel besprach (siehe "Die where Klausel"), aber es gibt eigentlich drei verschiedene Abfrageklauseln, die diese Rolle spielen. Die zweite ist die having Klausel, aber ihre Aufgabe ist es, Zeilen auf der Grundlage von gruppierten Daten zu filtern. Nehmen wir eine andere Tabelle, Supplier, um zu zeigen, wie das funktioniert. Hier ist die Definition von Supplier:

PUBLIC>describe table supplier;
+-------------+--------------+--------+-------+---------+...
| name        | type         | kind   | null? | default |...
|-------------+--------------+--------+-------+---------+...
| S_SUPPKEY   | NUMBER(38,0) | COLUMN | N     | NULL    |...
| S_NAME      | VARCHAR(25)  | COLUMN | N     | NULL    |...
| S_ADDRESS   | VARCHAR(40)  | COLUMN | N     | NULL    |...
| S_NATIONKEY | NUMBER(38,0) | COLUMN | N     | NULL    |...
| S_PHONE     | VARCHAR(15)  | COLUMN | N     | NULL    |...
| S_ACCTBAL   | NUMBER(12,2) | COLUMN | N     | NULL    |...
| S_COMMENT   | VARCHAR(101) | COLUMN | Y     | NULL    |...
+-------------+--------------+--------+-------+---------+...

Die Tabelle Supplier enthält die Spalte s_nationkey, die eine Verbindung zum Primärschlüssel der Tabelle Nation (n_nationkey) darstellt. Die nächste Abfrage zählt die Anzahl der Anbieter in jeder Nation:

PUBLIC>select n_name as nation_name,
         count(*) as number_of_suppliers
       from supplier join nation
       on supplier.s_nationkey = nation.n_nationkey
       group by n_name;
+----------------+---------------------+
| NATION_NAME    | NUMBER_OF_SUPPLIERS |
|----------------+---------------------|
| PERU           |                 421 |
| ETHIOPIA       |                 380 |
| ARGENTINA      |                 413 |
| MOROCCO        |                 373 |
| IRAQ           |                 438 |
| UNITED KINGDOM |                 390 |
| UNITED STATES  |                 393 |
| CANADA         |                 412 |
| RUSSIA         |                 401 |
| ROMANIA        |                 398 |
| BRAZIL         |                 397 |
| EGYPT          |                 415 |
| INDONESIA      |                 405 |
| ALGERIA        |                 420 |
| VIETNAM        |                 399 |
| JORDAN         |                 362 |
| JAPAN          |                 377 |
| SAUDI ARABIA   |                 411 |
| KENYA          |                 376 |
| CHINA          |                 407 |
| GERMANY        |                 396 |
| FRANCE         |                 402 |
| IRAN           |                 393 |
| INDIA          |                 415 |
| MOZAMBIQUE     |                 406 |
+----------------+---------------------+

In jedem der 25 Länder gibt es Anbieter, wobei Jordanien die wenigsten Anbieter hat (362) und der Irak die meisten (438). Wenn du nur die Länder abrufen möchtest, die mehr als 400 Lieferanten haben, kannst du eine having Klausel hinzufügen, die eine Filterbedingung für die Ergebnisse der Funktion count() enthält. So würde die aussehen:

PUBLIC>select n_name as nation_name,
         count(*) as number_of_suppliers
       from supplier join nation
       on supplier.s_nationkey = nation.n_nationkey
       group by n_name
       having count(*) > 400;
+--------------+---------------------+
| NATION_NAME  | NUMBER_OF_SUPPLIERS |
|--------------+---------------------|
| PERU         |                 421 |
| ARGENTINA    |                 413 |
| IRAQ         |                 438 |
| CANADA       |                 412 |
| RUSSIA       |                 401 |
| EGYPT        |                 415 |
| INDONESIA    |                 405 |
| ALGERIA      |                 420 |
| SAUDI ARABIA |                 411 |
| CHINA        |                 407 |
| FRANCE       |                 402 |
| INDIA        |                 415 |
| MOZAMBIQUE   |                 406 |
+--------------+---------------------+

Du kannst sowohl where als auch having Klauseln in derselben Abfrage haben, aber alle Bedingungen in der where Klausel werden vor der Gruppierung der Zeilen ausgewertet, während die Bedingungen in der having Klausel ausgewertet werden , nachdem die Zeilen gruppiert wurden. Hier ist ein Beispiel mit mehreren Filtern:

PUBLIC>select n_name as nation_name,
         count(*) as number_of_suppliers
       from supplier join nation
       on supplier.s_nationkey = nation.n_nationkey
       where n_name like '%A'
       group by n_name
       having count(*) > 400;
+--------------+---------------------+
| NATION_NAME  | NUMBER_OF_SUPPLIERS |
|--------------+---------------------|
| ARGENTINA    |                 413 |
| CHINA        |                 407 |
| INDIA        |                 415 |
| CANADA       |                 412 |
| RUSSIA       |                 401 |
| INDONESIA    |                 405 |
| SAUDI ARABIA |                 411 |
| ALGERIA      |                 420 |
+--------------+---------------------+

Diese Abfrage findet zunächst Lieferanten in Ländern, deren Name auf A endet, summiert die Anzahl der Lieferanten für jedes Land und verwirft dann alle Zeilen, deren Anzahl kleiner oder gleich 400 ist. Die having Klausel wird zusammen mit der group by Klausel in Kapitel 7 behandelt.

Die Qualifizierungsklausel

Bisher hast du zwei verschiedene Klauseln gesehen, die zum Filtern verwendet werden: where und having. Die dritte Klausel , die für die Filterung verwendet wird, ist qualify, aber sie ist eine Spezialklausel, die nur für die Filterung von Zeilen auf der Grundlage der Ergebnisse von Fensterfunktionen verwendet wird, die für mehrere Zwecke verwendet werden, einschließlich der Zuweisung von Rangfolgen. Zur Veranschaulichung wird im nächsten Beispiel jeder Zeile in der Tabelle Nation ein Rang zugewiesen, der auf der Anzahl der Zeichen im Namen basiert. Dazu wird die eingebaute Funktion length() verwendet:

PUBLIC>select n_name,
         rank() over (order by length(n_name) desc) as length_rank
       from nation;
+----------------+-------------+
| N_NAME         | LENGTH_RANK |
|----------------+-------------|
| UNITED KINGDOM |           1 |
| UNITED STATES  |           2 |
| SAUDI ARABIA   |           3 |
| MOZAMBIQUE     |           4 |
| ARGENTINA      |           5 |
| INDONESIA      |           5 |
| ETHIOPIA       |           7 |
| MOROCCO        |           8 |
| ALGERIA        |           8 |
| VIETNAM        |           8 |
| ROMANIA        |           8 |
| GERMANY        |           8 |
| JORDAN         |          13 |
| FRANCE         |          13 |
| CANADA         |          13 |
| RUSSIA         |          13 |
| BRAZIL         |          13 |
| JAPAN          |          18 |
| KENYA          |          18 |
| EGYPT          |          18 |
| CHINA          |          18 |
| INDIA          |          18 |
| IRAQ           |          23 |
| PERU           |          23 |
| IRAN           |          23 |
+----------------+-------------+

Die Funktion rank() wird verwendet, um für jede Zeile eine Rangfolge zu erstellen . Die höchste Rangfolge erhält Großbritannien mit 14 Zeichen, die niedrigsten Rangfolgen der Irak, Peru und Iran mit jeweils nur 4 Zeichen. Ohne näher auf die Funktion rank() einzugehen (die in Kapitel 14 behandelt wird), ändern wir die vorherige Abfrage so ab, dass sie nur die Zeilen mit einem Ranking von 5 oder weniger zurückgibt, indem wir eine qualify Klausel hinzufügen:

PUBLIC>select n_name,
         rank() over (order by length(n_name) desc) as length_rank
       from nation
       qualify length_rank <= 5;
+----------------+-------------+
| N_NAME         | LENGTH_RANK |
|----------------+-------------|
| UNITED KINGDOM |           1 |
| UNITED STATES  |           2 |
| SAUDI ARABIA   |           3 |
| MOZAMBIQUE     |           4 |
| ARGENTINA      |           5 |
| INDONESIA      |           5 |
+----------------+-------------+

Diese Version der Abfrage liefert 6 Zeilen, da sowohl Argentinien als auch Indonesien mit jeweils 9 Zeichen auf Platz 5 liegen. Die qualify Klausel wird in Kapitel 14 behandelt.

Die Reihenfolge nach Klausel

Im Allgemeinen sind die Ergebnisse von Abfragen nicht in einer bestimmten Reihenfolge angeordnet. Wenn du deine Ergebnisse sortieren möchtest, z. B. alphabetisch, numerisch oder chronologisch, kannst du eine order by Klausel am Ende deiner Abfrage hinzufügen. Die order by Klausel kann ein oder mehrere Elemente aus deiner select Klausel enthalten und sich entweder auf deren Namen oder Position beziehen.

Die Tabelle Supplier enthält die Spalte s_acctbal, die vermutlich einen Betrag enthält, der jedem Lieferanten geschuldet wird. Das nächste Beispiel sortiert die Ergebnisse nach s_acctbal in absteigender Reihenfolge:

PUBLIC>select s_name, s_acctbal
       from supplier
       order by s_acctbal desc;
+--------------------+-----------+
| S_NAME             | S_ACCTBAL |
|--------------------+-----------|
| Supplier#000006343 |   9998.20 |
| Supplier#000002522 |   9997.04 |
| Supplier#000000892 |   9993.46 |
| Supplier#000002543 |   9992.70 |
| Supplier#000001833 |   9992.26 |
| Supplier#000009966 |   9991.00 |
| Supplier#000002892 |   9989.02 |
| Supplier#000008875 |   9984.69 |
| Supplier#000002331 |   9984.20 |
| Supplier#000007895 |   9977.32 |
... <7,380 rows omitted>
| Supplier#000003627 |   -986.14 |
| Supplier#000001907 |   -987.45 |
| Supplier#000001654 |   -988.37 |
| Supplier#000001870 |   -989.05 |
| Supplier#000008224 |   -989.86 |
| Supplier#000001764 |   -990.13 |
| Supplier#000005298 |   -990.16 |
| Supplier#000008927 |   -995.53 |
| Supplier#000007259 |   -997.61 |
| Supplier#000009795 |   -998.22 |
+--------------------+-----------+

Die Tabelle Supplier hat 7.400 Zeilen, daher habe ich die meisten davon ausgelassen, aber du kannst sehen, wie der Wert s_acctbal über die Zeilen in der Ergebnismenge abnimmt. Die Spalte, die für die Sortierung verwendet wird, könnte auch durch ihre Position in der select Klausel angegeben werden, die in diesem Fall 2 wäre:

PUBLIC>select s_name, s_acctbal
       from supplier
       order by 2 desc;
+--------------------+-----------+
| S_NAME             | S_ACCTBAL |
|--------------------+-----------|
| Supplier#000006343 |   9998.20 |
| Supplier#000002522 |   9997.04 |
| Supplier#000000892 |   9993.46 |
| Supplier#000002543 |   9992.70 |
| Supplier#000001833 |   9992.26 |
| Supplier#000009966 |   9991.00 |
| Supplier#000002892 |   9989.02 |
| Supplier#000008875 |   9984.69 |
| Supplier#000002331 |   9984.20 |
| Supplier#000007895 |   9977.32 |
... <7,390 rows omitted>
+--------------------+-----------+

Du kannst die Sortierreihenfolge entweder als absteigend (desc) oder aufsteigend (asc) angeben. Es gibt zwar kein eigenes Kapitel für die order by Klausel, aber du wirst sie in verschiedenen Beispielen in diesem Buch verwenden.

Die Begrenzungsklausel

Die Ergebnismenge von aus dem vorherigen Beispiel enthielt 7.400 Zeilen. Wäre es nicht toll, wenn du angeben könntest, dass nur eine Teilmenge zurückgegeben werden soll? Hier kommt die limit Klausel ins Spiel, mit der du angeben kannst, wie viele Zeilen zurückgegeben werden sollen, entweder ab der ersten Zeile oder ab einem bestimmten Offset. Hier ist die Abfrage aus dem vorigen Abschnitt, aber mit einer limit Klausel, um anzugeben, dass nur die ersten 10 Zeilen zurückgegeben werden sollen:

PUBLIC>select s_name, s_acctbal
         from supplier
         order by s_acctbal desc
         limit 10;
+--------------------+-----------+
| S_NAME             | S_ACCTBAL |
|--------------------+-----------|
| Supplier#000006343 |   9998.20 |
| Supplier#000002522 |   9997.04 |
| Supplier#000000892 |   9993.46 |
| Supplier#000002543 |   9992.70 |
| Supplier#000001833 |   9992.26 |
| Supplier#000009966 |   9991.00 |
| Supplier#000002892 |   9989.02 |
| Supplier#000008875 |   9984.69 |
| Supplier#000002331 |   9984.20 |
| Supplier#000007895 |   9977.32 |
+--------------------+-----------+

In diesem Beispiel sortiert der Server alle 7.400 Zeilen, wie in der order by Klausel angegeben, und gibt dann nur die ersten 10 Zeilen zurück. Du kannst auch die optionale Subklausel offset verwenden, um dem Server mitzuteilen, dass er bei einer bestimmten Zeile beginnen soll. Da ich weiß, dass es 7.400 Zeilen in der Tabelle Supplier gibt, kann ich einen Offset von 7.390 angeben, um die letzten 10 Zeilen in der Ergebnismenge zu sehen:

PUBLIC>select s_name, s_acctbal
       from supplier
       order by s_acctbal desc
       limit 10 offset 7390;
+--------------------+-----------+
| S_NAME             | S_ACCTBAL |
|--------------------+-----------|
| Supplier#000003627 |   -986.14 |
| Supplier#000001907 |   -987.45 |
| Supplier#000001654 |   -988.37 |
| Supplier#000001870 |   -989.05 |
| Supplier#000008224 |   -989.86 |
| Supplier#000001764 |   -990.13 |
| Supplier#000005298 |   -990.16 |
| Supplier#000008927 |   -995.53 |
| Supplier#000007259 |   -997.61 |
| Supplier#000009795 |   -998.22 |
+--------------------+-----------+

Es wäre zwar toll, wenn du limit -10 angeben könntest, um die letzten 10 Zeilen in der Ergebnismenge zu sehen, ohne die Gesamtzahl der Zeilen zu kennen, aber diese Funktion ist derzeit nicht verfügbar. Du kannst aber immer in die entgegengesetzte Richtung sortieren und die ersten 10 Zeilen auswählen:

PUBLIC>select s_name, s_acctbal
              from supplier
              order by s_acctbal asc
              limit 10;
+--------------------+-----------+
| S_NAME             | S_ACCTBAL |
|--------------------+-----------|
| Supplier#000009795 |   -998.22 |
| Supplier#000007259 |   -997.61 |
| Supplier#000008927 |   -995.53 |
| Supplier#000005298 |   -990.16 |
| Supplier#000001764 |   -990.13 |
| Supplier#000008224 |   -989.86 |
| Supplier#000001870 |   -989.05 |
| Supplier#000001654 |   -988.37 |
| Supplier#000001907 |   -987.45 |
| Supplier#000003627 |   -986.14 |
+--------------------+-----------+

Nachbereitung

Die Anweisung select erscheint auf den ersten Blick einfach, aber wenn du mehr und mehr der acht in diesem Kapitel vorgestellten Klauseln kombinierst, können Abfragen ziemlich anspruchsvoll werden. Noch interessanter wird es, wenn du Unterabfragen(Kapitel 8), bedingte Logik(Kapitel 10) und Fensterfunktionen(Kapitel 14) einbeziehst. In den Kapiteln 5 und 6 werden einige andere SQL-Datenanweisungen vorgestellt, z. B. insert und update, bei denen einige der gleichen Klauseln verwendet werden, die auch bei der Erstellung von select verwendet werden.

Teste dein Wissen

Die folgenden Übungen dienen dazu, dein Verständnis der Erklärung select zu vertiefen. Die Lösungen findest du in "Kapitel 1" im Anhang B.

Übung 1-1

Schreibe eine Abfrage, um die Spalten n_nationkey und n_name aus der Tabelle Nation abzurufen. Sortiere die Zeilen nach den Werten von n_name.

Übung 1-2

Schreibe eine Abfrage, um die Spalten n_nationkey und n_name aus der Tabelle Nation abzurufen, aber nur für die Zeilen mit einem Wert von 3 für n_regionkey.

Übung 1-3

Schreibe eine Abfrage, um die Spalten n_nationkey und n_name aus der Tabelle Nation abzurufen, und verbinde sie mit der Tabelle Region (unter Verwendung der Spalte r_regionkey ), um nur die Nationen abzurufen, die zur Region Afrika gehören (r_name = 'AFRICA').

Übung 1-4

Rufe die Spalten s_name und s_acctbal aus der Tabelle Supplier ab. Sortiere nach s_acctbal in absteigender Reihenfolge und rufe nur die ersten 10 Zeilen ab (das sind die 10 Lieferanten mit den höchsten s_acctbal Werten).

Get Snowflake SQL und Skripting lernen now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.