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.
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 einefrom
Klausel. Diefrom
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.
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.
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.