

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

# SELECT
<a name="sql-commands-select-spark"></a>

Der SELECT-Befehl gibt Zeilen aus Tabellen und benutzerdefinierten Funktionen zurück.

Die folgenden SELECT-SQL-Befehle, -Klauseln und Mengenoperatoren werden in AWS Clean Rooms Spark SQL unterstützt:

**Topics**
+ [SELECT list](sql-function-select-list-spark.md)
+ [WITH-Klausel](WITH_clause.md)
+ [FROM-Klausel](FROM_clause30.md)
+ [JOIN-Klausel](join-clause.md)
+ [WHERE-Klausel](WHERE_clause.md)
+ [VALUES-Klausel](VALUES.md)
+ [GROUP BY-Klausel](GROUP_BY_clause.md)
+ [HAVING-Klausel](HAVING_clause.md)
+ [Satzoperatoren](UNION.md)
+ [ORDER BY-Klausel](ORDER_BY_clause.md)
+ [Beispiele für Unterabfragen](Subquery_examples.md)
+ [Korrelierte Unterabfragen](correlated_subqueries.md)

Die Syntax, die Argumente und einige Beispiele stammen aus der [Apache Spark SQL-Referenz.](https://spark.apache.org/docs/latest/api/sql/)

# SELECT list
<a name="sql-function-select-list-spark"></a>

Die SELECT list Namen der Spalten, Funktionen und Ausdrücke, die die Abfrage zurückgeben soll. Der Liste stellt die Ausgabe der Abfrage dar.

## Syntax
<a name="sql-function-select-list-syntax-spark"></a>

```
SELECT
[ DISTINCT ] | expression [ AS column_alias ] [, ...]
```

## Parameters
<a name="sql-function-select-list-parameters-spark"></a>

DISTINCT  
Eine Option, die duplizierte Zeilen aus dem Ergebnissatz entfernt, basierend auf übereinstimmenden Werten in einer oder mehreren Spalten.

*expression*  
Ein Ausdruck, der aus einer oder mehreren Spalten gebildet wird, die in den Tabellen vorhanden sind, die von der Abfrage referenziert werden. Ein Ausdruck kann SQL-Funktionen enthalten. Beispiel:

```
coalesce(dimension, 'stringifnull') AS column_alias
```

AS column\$1alias

Ein temporärer Name für die Spalte, der im endgültigen Ergebnissatz verwendet wird. Das AS-Schlüsselwort ist optional. Beispiel:

```
coalesce(dimension, 'stringifnull') AS dimensioncomplete
```

Wenn Sie keinen Alias für einen Ausdruck angeben, bei dem es sich nicht um einen einfachen Spaltennamen handelt, wendet der Ergebnissatz einen Standardnamen auf diese Spalte an.

**Anmerkung**  
Der Alias wird sofort nach seiner Definition in der Zielliste erkannt. Sie können einen Alias nicht in anderen Ausdrücken verwenden, die danach in derselben Zielliste definiert wurden. 

# WITH-Klausel
<a name="WITH_clause"></a>

Eine WITH-Klausel ist eine optionale Klausel, die der SELECT-Liste in einer Abfrage vorangeht. Die WITH-Klausel definiert einen oder mehrere *allgemeine Tabellenausdrücke* (CTE). Jeder allgemeine Tabellenausdruck (CTE) definiert eine temporäre Tabelle, die einer Ansichtdefinition ähnelt. Sie können diese temporären Tabellen in der FROM-Klausel referenzieren. Sie werden nur verwendet, während die Abfrage, zu der sie gehören, ausgeführt wird. Jede CTE in der WITH-Klausel gibt einen Tabellennamen, eine optionale Liste von Spaltennamen und einen Abfrageausdruck an, der in eine Tabelle evaluiert wird (eine SELECT-Anweisung).

Unterabfragen mit einer WITH-Klausel sind eine effiziente Art, Tabellen zu definieren, die während der Ausführung einer einzelnen Abfrage verwendet werden können. In allen Fällen können dieselben Ergebnisse erzielt werden, indem im Hauptteil der SELECT-Anweisung Unterabfragen verwendet werden. Unterabfragen mit WITH-Klauseln können jedoch leichter geschrieben und gelesen werden. Wenn möglich, werden Unterabfragen mit WITH-Klauseln, die mehrmals referenziert werden, als gemeinsame Unterausdrücke optimiert. Das bedeutet, dass es möglich sein kann, eine WITH-Unterabfrage einmal zu evaluieren und die Ergebnisse wiederzuverwenden. (Beachten Sie, dass gemeinsame Unterausdrücke nicht auf diejenigen begrenzt sind, die in der WITH-Klausel definiert sind.)

## Syntax
<a name="WITH_clause-synopsis"></a>

```
[ WITH common_table_expression [, common_table_expression , ...] ]
```

wobei *common\$1table\$1expression* nicht rekursiv sein kann. Dies ist die nicht-rekursive Form: 

```
CTE_table_name AS ( query )
```

## Parameters
<a name="WITH_clause-parameters"></a>

 *common\$1table\$1expression*   
Definiert eine temporäre Tabelle, auf die Sie in der [FROM-Klausel](FROM_clause30.md) verweisen können und die nur während der Ausführung der Abfrage verwendet wird, zu der sie gehört. 

 *CTE\$1table\$1name*   
Ein eindeutiger Name für eine temporäre Tabelle, die die Ergebnisse einer Unterabfrage mit WITH-Klausel definiert. Sie können in einer einzelnen WITH-Klausel keine duplizierten Namen verwenden. Jede Unterabfrage muss einen Tabellennamen erhalten, der in der referenziert werden kann [FROM-Klausel](FROM_clause30.md).

 *query*   
 Jede SELECT-Abfrage, die unterstützt. AWS Clean Rooms Siehe [SELECT](sql-commands-select-spark.md). 

## Nutzungshinweise
<a name="WITH_clause-usage-notes"></a>

Sie können eine WITH-Klausel in der folgenden SQL-Anweisung verwenden: 
+ SELECT, WITH, UNION, UNION ALL, INTERSECT, INTERSECT ALL, EXCEPT oder EXCEPT ALL 

Wenn die FROM-Klausel einer Abfrage, die eine WITH-Klausel enthält, keine der Tabellen referenziert, die von der WITH-Klausel definiert werden, wird die WITH-Klausel ignoriert, und die Abfrage wird wie normal ausgeführt.

Eine Tabelle, die von einer Unterabfrage mit WITH-Klausel definiert ist, kann nur im Bereich der SELECT-Abfrage referenziert werden, die die WITH-Klausel beginnt. Sie können beispielsweise eine solche Tabelle in der FROM-Klausel einer Unterabfrage in der SELECT-Liste, in einer WHERE-Klausel oder in einer HAVING-Klausel referenzieren. Sie können eine WITH-Klausel nicht in einer Unterabfrage verwenden und ihre Tabelle in der FROM-Klausel der Hauptabfrage oder einer anderen Unterabfrage referenzieren. Dieses Abfragemuster führt zu einer Fehlermeldung der Art `relation table_name doesn't exist` für die Tabelle der WITH-Klausel.

Sie können innerhalb einer Unterabfrage mit WITH-Klausel keine weitere WITH-Klausel angeben.

Sie können keine Vorausreferenzen auf Tabellen erstellen, die durch Unterabfragen mit WITH-Klauseln definiert werden. Die folgende Abfrage gibt beispielsweise aufgrund der Vorausreferenz auf die Tabelle W2 in der Definition der Tabelle W1 einen Fehler zurück: 

```
with w1 as (select * from w2), w2 as (select * from w1)
select * from sales;
ERROR:  relation "w2" does not exist
```

## Beispiele
<a name="WITH_clause-examples"></a>

Im folgenden Beispiel wird der einfachste mögliche Fall einer Abfrage gezeigt, die eine WITH-Klausel enthält. Die WITH-Abfrage namens VENUECOPY wählt alle Zeilen aus der Tabelle VENUE aus. Die Hauptabfrage wählt anschließend alle Zeilen aus VENUECOPY aus. Die Tabelle VENUECOPY besteht nur für die Dauer dieser Abfrage. 

```
with venuecopy as (select * from venue)
select * from venuecopy order by 1 limit 10;
```

```
 venueid |         venuename          |    venuecity    | venuestate | venueseats
---------+----------------------------+-----------------+------------+------------
1 | Toyota Park                | Bridgeview      | IL         |          0
2 | Columbus Crew Stadium      | Columbus        | OH         |          0
3 | RFK Stadium                | Washington      | DC         |          0
4 | CommunityAmerica Ballpark  | Kansas City     | KS         |          0
5 | Gillette Stadium           | Foxborough      | MA         |      68756
6 | New York Giants Stadium    | East Rutherford | NJ         |      80242
7 | BMO Field                  | Toronto         | ON         |          0
8 | The Home Depot Center      | Carson          | CA         |          0
9 | Dick's Sporting Goods Park | Commerce City   | CO         |          0
v     10 | Pizza Hut Park             | Frisco          | TX         |          0
(10 rows)
```

Im folgenden Beispiel wird eine WITH-Klausel gezeigt, die zwei Tabellen namens VENUE\$1SALES und TOP\$1VENUES erstellt. Die zweite WITH-Abfragetabelle wählt aus der ersten aus. Die WHERE-Klausel des Hauptabfrageblocks enthält eine Unterabfrage, die die Tabelle TOP\$1VENUES einschränkt. 

```
with venue_sales as
(select venuename, venuecity, sum(pricepaid) as venuename_sales
from sales, venue, event
where venue.venueid=event.venueid and event.eventid=sales.eventid
group by venuename, venuecity),

top_venues as
(select venuename
from venue_sales
where venuename_sales > 800000)

select venuename, venuecity, venuestate,
sum(qtysold) as venue_qty,
sum(pricepaid) as venue_sales
from sales, venue, event
where venue.venueid=event.venueid and event.eventid=sales.eventid
and venuename in(select venuename from top_venues)
group by venuename, venuecity, venuestate
order by venuename;
```

```
        venuename       |   venuecity   | venuestate | venue_qty | venue_sales
------------------------+---------------+------------+-----------+-------------
August Wilson Theatre   | New York City | NY         |      3187 |  1032156.00
Biltmore Theatre        | New York City | NY         |      2629 |   828981.00
Charles Playhouse       | Boston        | MA         |      2502 |   857031.00
Ethel Barrymore Theatre | New York City | NY         |      2828 |   891172.00
Eugene O'Neill Theatre  | New York City | NY         |      2488 |   828950.00
Greek Theatre           | Los Angeles   | CA         |      2445 |   838918.00
Helen Hayes Theatre     | New York City | NY         |      2948 |   978765.00
Hilton Theatre          | New York City | NY         |      2999 |   885686.00
Imperial Theatre        | New York City | NY         |      2702 |   877993.00
Lunt-Fontanne Theatre   | New York City | NY         |      3326 |  1115182.00
Majestic Theatre        | New York City | NY         |      2549 |   894275.00
Nederlander Theatre     | New York City | NY         |      2934 |   936312.00
Pasadena Playhouse      | Pasadena      | CA         |      2739 |   820435.00
Winter Garden Theatre   | New York City | NY         |      2838 |   939257.00
(14 rows)
```

In den folgenden beiden Beispielen werden die Regeln für den Bereich der Tabellenreferenzen auf der Basis von Unterabfragen mit WITH-Klausel gezeigt. Die erste Abfrage wird ausgeführt. Die zweite Abfrage schlägt jedoch mit einem erwarteten Fehler fehl. Die erste Abfrage enthält eine Unterabfrage mit WITH-Klausel innerhalb der SELECT-Liste der Hauptabfrage. Die von der WITH-Klausel definierte Tabelle (HOLIDAYS) wird in der FROM-Klausel der Unterabfrage in der SELECT-Liste referenziert: 

```
select caldate, sum(pricepaid) as daysales,
(with holidays as (select * from date where holiday ='t')
select sum(pricepaid)
from sales join holidays on sales.dateid=holidays.dateid
where caldate='2008-12-25') as dec25sales
from sales join date on sales.dateid=date.dateid
where caldate in('2008-12-25','2008-12-31')
group by caldate
order by caldate;

caldate   | daysales | dec25sales
-----------+----------+------------
2008-12-25 | 70402.00 |   70402.00
2008-12-31 | 12678.00 |   70402.00
(2 rows)
```

Die zweite Abfrage schlägt fehl, weil sie versucht, die Tabelle HOLIDAYS in der Hauptabfrage und in der Unterabfrage der SELECT-Liste zu referenzieren. Die Referenzen der Hauptabfrage liegen außerhalb des Bereichs. 

```
select caldate, sum(pricepaid) as daysales,
(with holidays as (select * from date where holiday ='t')
select sum(pricepaid)
from sales join holidays on sales.dateid=holidays.dateid
where caldate='2008-12-25') as dec25sales
from sales join holidays on sales.dateid=holidays.dateid
where caldate in('2008-12-25','2008-12-31')
group by caldate
order by caldate;

ERROR:  relation "holidays" does not exist
```

# FROM-Klausel
<a name="FROM_clause30"></a>

Die -Klausel in einer Abfrage listet die Tabellenreferenzen (Tabellen, Ansichten und Unterabfragen) auf, aus denen Daten ausgewählt werden. Wenn mehrere Tabellenreferenzen aufgelistet werden, muss ein Join für die Tabellen ausgeführt werden, indem entweder in der FROM-Klausel oder in der WHERE-Klausel die entsprechende Syntax verwendet wird. Wenn keine Join-Kriterien angegeben werden, verarbeitet das System die Abfrage als Kreuz-Join (kartesisches Produkt). 

**Topics**
+ [Syntax](#FROM_clause30-synopsis)
+ [Parameters](#FROM_clause30-parameters)
+ [Nutzungshinweise](#FROM_clause_usage_notes)

## Syntax
<a name="FROM_clause30-synopsis"></a>

```
FROM table_reference [, ...]
```

wobei *table\$1reference* eins der folgenden ist: 

```
with_subquery_table_name | table_name | ( subquery ) [ [ AS ] alias ]
table_reference [ NATURAL ] join_type table_reference [ USING ( join_column [, ...] ) ]
table_reference [ INNER ] join_type table_reference ON expr
```

## Parameters
<a name="FROM_clause30-parameters"></a>

 *with\$1subquery\$1table\$1name*   
Eine Tabelle, die von einer Unterabfrage in der definiert wird [WITH-Klausel](WITH_clause.md). 

 *table\$1name*   
Der Name einer Tabelle oder Ansicht. 

 *alias*   
Der temporäre alternative Name für eine Tabelle oder Ansicht. Für eine Tabelle, die von einer Unterabfrage abgeleitet wird, muss ein Alias bereitgestellt werden. In anderen Tabellenreferenzen sind Aliasnamen optional. Das AS Schlüsselwort ist immer optional. Tabellenaliasnamen stellen eine bequeme Abkürzung für die Identifizierung von Tabellen in anderen Teilen einer Abfrage dar, beispielsweise in der WHERE-Klausel.   
Beispiel:   

```
select * from sales s, listing l
where s.listid=l.listid
```
Wenn Sie definieren, dass ein Tabellenalias definiert ist, muss der Alias verwendet werden, um in der Abfrage auf diese Tabelle zu verweisen.   
Wenn die Abfrage beispielsweise so ist`SELECT "tbl"."col" FROM "tbl" AS "t"`, würde die Abfrage fehlschlagen, weil der Tabellenname jetzt im Wesentlichen überschrieben wird. Eine gültige Abfrage wäre in diesem Fall. `SELECT "t"."col" FROM "tbl" AS "t"`

 *column\$1alias*   
Der temporäre alternative Name für eine Spalte in einer Tabelle oder Ansicht. 

 *subquery*   
Ein Abfrageausdruck, der zu einer Tabelle evaluiert wird. Die Tabelle ist nur für die Dauer der Abfrage vorhanden und erhält in der Regel einen Namen oder einen *Alias*. Ein Alias ist jedoch nicht erforderlich. Sie können auch Spaltennamen für Tabellen definieren, die von Unterabfragen abgeleitet werden. Die Vergabe von Spaltenaliasnamen ist wichtig, wenn Sie für die Ergebnisse von Unterabfragen einen Join mit anderen Tabellen ausführen möchten und wenn Sie diese Spalten an anderer Stelle in der Abfrage auswählen oder einschränken möchten.   
Eine Unterabfrage kann eine ORDER BY-Klausel enthalten. Diese Klausel hat jedoch keine Auswirkungen, wenn nicht auch eine LIMIT- oder OFFSET-Klausel angegeben ist. 

NATURAL   
Definiert einen Join, der automatisch alle Paare identisch benannter Spalten in den beiden Tabellen als Joining-Spalten verwendet. Es ist keine explizite Join-Bedingung erforderlich. Wenn die Tabellen CATEGORY und EVENT beispielsweise beide Spalten namens CATID besitzen, ist ein Join ihrer CATID-Spalten ein NATURAL-Join dieser Tabellen.   
Wenn ein NATURAL-Join angegeben ist, in den Tabellen, für die ein Join ausgeführt werden soll, jedoch keine identisch benannten Spaltenpaare vorhanden sind, wird für die Abfrage standardmäßig ein Kreuz-Join ausgeführt. 

 *join\$1type*   
Geben Sie eine der folgenden Join-Arten an:   
+ [INNER] JOIN 
+ LEFT [OUTER] JOIN 
+ RIGHT [OUTER] JOIN 
+ FULL [OUTER] JOIN 
+ CROSS JOIN 
Kreuz-Joins sind nicht qualifizierte Joins. Sie geben das kartesische Produkt der beiden Tabellen zurück.   
Interne und externe Joins sind qualifizierte Joins. Sie sind entweder implizit (in natürlichen Joins), mit der ON- oder USING-Syntax in der FROM-Klausel oder mit einer WHERE-Klauselbedingung qualifiziert.   
Ein interner Join gibt nur übereinstimmende Zeilen zurück, basierend auf der Join-Bedingung oder der Liste der Joining-Spalten. Ein externer Join gibt alle Zeilen zurück, die der entsprechende interne Join zurückgeben würde, und zusätzlich nicht übereinstimmende Zeilen aus der Tabelle „links“, aus der Tabelle „rechts“ oder aus beiden Tabellen. Die linke Tabelle wird zuerst aufgelistet. Die rechte Tabelle wird als zweite Tabelle aufgelistet. Die nicht übereinstimmenden Zeilen enthalten NULL-Werte, um die Lücken in den Ausgabespalten zu füllen. 

ON *join\$1condition*   
Eine Join-Spezifikation, in der die Joining-Spalten als eine Bedingung angegeben werden, die dem Schlüsselwort ON folgt. Beispiel:   

```
sales join listing
on sales.listid=listing.listid and sales.eventid=listing.eventid
```

USING ( *join\$1column* [, ...] )   
Eine Join-Spezifikation, in der die Joining-Spalten in Klammern angegeben werden. Wenn mehrere Joining-Spalten angegeben werden, werden sie durch Komma abgetrennt. Das Schlüsselwort USING muss der Liste vorangestellt werden. Zum Beispiel:   

```
sales join listing
using (listid,eventid)
```

## Nutzungshinweise
<a name="FROM_clause_usage_notes"></a>

Joining-Spalten müssen vergleichbare Datentypen haben. 

Ein NATURAL- oder -USING-Join enthält jeweils nur eine Spalte jedes Joining-Spaltenpaars im Zwischenergebnissatz. 

Ein Join mit der ON-Syntax enthält beide Joining-Spalten im Zwischenergebnissatz. 

Weitere Informationen finden Sie auch unter [WITH-Klausel](WITH_clause.md). 

# JOIN-Klausel
<a name="join-clause"></a>

Eine SQL JOIN-Klausel wird verwendet, um die Daten aus zwei oder mehr Tabellen basierend auf gemeinsamen Feldern zu kombinieren. Die Ergebnisse können sich je nach festgelegter Join-Methode ändern oder nicht. Externe Joins nach links und rechts behalten die Werte aus einer der Tabellen, für die ein Join ausgeführt wurde, wenn in der anderen Tabelle keine Übereinstimmung gefunden wurde. 

Die Kombination aus dem JOIN-Typ und der Join-Bedingung bestimmt, welche Zeilen in der endgültigen Ergebnismenge enthalten sind. Die SELECT- und WHERE-Klauseln steuern dann, welche Spalten zurückgegeben werden und wie die Zeilen gefiltert werden. Das Verständnis der verschiedenen JOIN-Typen und deren effektive Verwendung ist eine wichtige Fähigkeit in SQL, da Sie damit Daten aus mehreren Tabellen auf flexible und leistungsstarke Weise kombinieren können.

## Syntax
<a name="join-clause-syntax"></a>

```
SELECT column1, column2, ..., columnn
FROM table1
join_type table2
ON table1.column = table2.column;
```

## Parameters
<a name="join-clause-parameters"></a>

 *WÄHLEN SIE Spalte1, Spalte2,..., SpalteN*   
Die Spalten, die Sie in die Ergebnismenge aufnehmen möchten. Sie können Spalten aus einer oder beiden der am JOIN beteiligten Tabellen auswählen. 

 *AUS Tabelle1*   
Die erste (linke) Tabelle in der JOIN-Operation.

 *[VERKNÜPFEN \$1 INNERE VERKNÜPFUNG \$1 LINKE [ÄUSSERE] VERKNÜPFUNG \$1 RECHTE [ÄUSSERE] VERKNÜPFUNG \$1 VOLLSTÄNDIGE [ÄUSSERE] VERKNÜPFUNG] Tabelle2:*   
Der Typ des auszuführenden JOINS. JOIN oder INNER JOIN gibt nur die Zeilen mit übereinstimmenden Werten in beiden Tabellen zurück.   
LEFT [OUTER] JOIN gibt alle Zeilen aus der linken Tabelle mit übereinstimmenden Zeilen aus der rechten Tabelle zurück.   
RIGHT [OUTER] JOIN gibt alle Zeilen aus der rechten Tabelle mit den entsprechenden Zeilen aus der linken Tabelle zurück.   
FULL [OUTER] JOIN gibt alle Zeilen aus beiden Tabellen zurück, unabhängig davon, ob eine Übereinstimmung vorliegt oder nicht.   
CROSS JOIN erzeugt ein kartesisches Produkt der Zeilen aus den beiden Tabellen.

 *ON Tabelle1.Spalte = Tabelle2.Spalte*   
Die Join-Bedingung, die angibt, wie die Zeilen in den beiden Tabellen abgeglichen werden. Die Join-Bedingung kann auf einer oder mehreren Spalten basieren.

 *WHERE-Bedingung:*   
Eine optionale Klausel, mit der die Ergebnismenge anhand einer bestimmten Bedingung weiter gefiltert werden kann. 

## Beispiel
<a name="Join_examples"></a>

Das folgende Beispiel ist ein Join zwischen zwei Tabellen mit der USING-Klausel. In diesem Fall werden die Spalten listid und eventid als Join-Spalten verwendet. Die Ergebnisse sind auf 5 Zeilen begrenzt.

```
select listid, listing.sellerid, eventid, listing.dateid, numtickets
from listing join sales
using (listid, eventid)
order by 1
limit 5;

listid | sellerid | eventid | dateid | numtickets
-------+----------+---------+--------+-----------
1      | 36861    | 7872    | 1850   | 10
4      | 8117     | 4337    | 1970   | 8
5      | 1616     | 8647    | 1963   | 4
5      | 1616     | 8647    | 1963   | 4
6      | 47402    | 8240    | 2053   | 18
```

# JOIN-Typen
<a name="join-types"></a>

## INNER
<a name="inner-join"></a>

Dies ist der Standard-Join-Typ. Gibt die Zeilen zurück, deren Werte in beiden Tabellenverweisen übereinstimmen. 

Der INNER JOIN ist der in SQL am häufigsten verwendete Join-Typ. Es ist eine leistungsstarke Methode, um Daten aus mehreren Tabellen auf der Grundlage einer gemeinsamen Spalte oder einer Gruppe von Spalten zu kombinieren. 

**Syntax:**

```
SELECT column1, column2, ..., columnn
FROM table1
INNER JOIN table2
ON table1.column = table2.column;
```

Die folgende Abfrage gibt alle Zeilen zurück, in denen ein übereinstimmender customer\$1id-Wert zwischen den Tabellen „customers“ und „orders“ vorhanden ist. Das Resultset wird die Spalten customer\$1id, name, order\$1id und order\$1date enthalten.

```
SELECT customers.customer_id, customers.name, orders.order_id, orders.order_date
FROM customers
INNER JOIN orders
ON customers.customer_id = orders.customer_id;
```

Die folgende Abfrage ist ein innerer Join (ohne das Schlüsselwort JOIN) zwischen den Tabellen LISTING und SALES, wobei die LISTID aus der Tabelle LISTING zwischen 1 und 5 liegt. Diese Abfrage gleicht LISTID-Spaltenwerte in der Tabelle LISTING (linke Tabelle) und der Tabelle SALES (rechte Tabelle) ab. Die Ergebnisse zeigen, dass LISTID 1, 4 und 5 den Kriterien entsprechen.

```
select listing.listid, sum(pricepaid) as price, sum(commission) as comm
from listing, sales
where listing.listid = sales.listid
and listing.listid between 1 and 5
group by 1
order by 1;

listid | price  |  comm
-------+--------+--------
     1 | 728.00 | 109.20
     4 |  76.00 |  11.40
     5 | 525.00 |  78.75
```

Bei dem folgenden Beispiel handelt es sich um einen inneren Join mit der ON-Klausel. In diesem Fall werden NULL-Zeilen nicht zurückgegeben.

```
select listing.listid, sum(pricepaid) as price, sum(commission) as comm
from sales join listing
on sales.listid=listing.listid and sales.eventid=listing.eventid
where listing.listid between 1 and 5
group by 1
order by 1;

listid | price  |  comm
-------+--------+--------
     1 | 728.00 | 109.20
     4 |  76.00 |  11.40
     5 | 525.00 |  78.75
```

Die folgende Abfrage ist ein interner Join zweiter Unterabfragen in der FROM-Klausel. Die Abfrage ermittelt die Zahl der verkauften und nicht verkauften Tickets für verschiedene Veranstaltungskategorien (Konzerte und Shows). Die Unterabfragen mit FROM-Klausel sind *Tabellen*-Unterabfragen und können mehrere Spalten und Zeilen zurückgeben.

```
select catgroup1, sold, unsold
from
(select catgroup, sum(qtysold) as sold
from category c, event e, sales s
where c.catid = e.catid and e.eventid = s.eventid
group by catgroup) as a(catgroup1, sold)
join
(select catgroup, sum(numtickets)-sum(qtysold) as unsold
from category c, event e, sales s, listing l
where c.catid = e.catid and e.eventid = s.eventid
and s.listid = l.listid
group by catgroup) as b(catgroup2, unsold)

on a.catgroup1 = b.catgroup2
order by 1;

catgroup1 |  sold  | unsold
----------+--------+--------
Concerts  | 195444 |1067199
Shows     | 149905 | 817736
```

## LINKS [AUSSEN]
<a name="left-outer-join"></a>

Gibt alle Werte aus der linken Tabellenreferenz und die übereinstimmenden Werte aus der rechten Tabellenreferenz zurück oder hängt NULL an, wenn es keine Übereinstimmung gibt. Es wird auch als *Left Outer Join* bezeichnet. 

Es gibt alle Zeilen aus der linken (ersten) Tabelle und die passenden Zeilen aus der rechten (zweiten) Tabelle zurück. Wenn es in der rechten Tabelle keine Übereinstimmung gibt, enthält die Ergebnismenge NULL-Werte für die Spalten aus der rechten Tabelle. Das Schlüsselwort OUTER kann weggelassen werden, und der Join kann einfach als LEFT JOIN geschrieben werden. Das Gegenteil von LEFT OUTER JOIN ist RIGHT OUTER JOIN, bei dem alle Zeilen aus der rechten Tabelle und die passenden Zeilen aus der linken Tabelle zurückgegeben werden.

**Syntax:**

```
SELECT column1, column2, ..., columnn
FROM table1
LEFT [OUTER] JOIN table2
ON table1.column = table2.column;
```

Die folgende Abfrage gibt alle Zeilen aus der Kundentabelle zusammen mit den entsprechenden Zeilen aus der Bestelltabelle zurück. Wenn ein Kunde keine Bestellungen hat, enthält das Resultset dennoch die Informationen dieses Kunden mit NULL-Werten für die Spalten order\$1id und order\$1date.

```
SELECT customers.customer_id, customers.name, orders.order_id, orders.order_date
FROM customers
LEFT OUTER JOIN orders
ON customers.customer_id = orders.customer_id;
```

Bei der folgenden Abfrage handelt es sich um einen linken, externen Join. Externe Joins nach links und rechts behalten die Werte aus einer der Tabellen, für die ein Join ausgeführt wurde, wenn in der anderen Tabelle keine Übereinstimmung gefunden wurde. Die Tabellen links und rechts werden in der Syntax als erste und zweite Tabelle aufgelistet. Es werden NULL-Werte verwendet, um die „Lücken“ im Ergebnissatz zu füllen. Diese Abfrage gleicht LISTID-Spaltenwerte in der Tabelle LISTING (linke Tabelle) und der Tabelle SALES (rechte Tabelle) ab. Die Ergebnisse zeigen, dass LISTIDs 2 und 3 zu keinen Verkäufen geführt haben.

```
select listing.listid, sum(pricepaid) as price, sum(commission) as comm
from listing left outer join sales on sales.listid = listing.listid
where listing.listid between 1 and 5
group by 1
order by 1;

listid | price  |  comm
-------+--------+--------
     1 | 728.00 | 109.20
     2 | NULL   | NULL
     3 | NULL   | NULL
     4 |  76.00 |  11.40
     5 | 525.00 |  78.75
```

## RECHTS [AUSSEN]
<a name="right-outer-join"></a>

Gibt alle Werte aus der rechten Tabellenreferenz und die übereinstimmenden Werte aus der linken Tabellenreferenz zurück oder hängt NULL an, wenn es keine Übereinstimmung gibt. Es wird auch als *rechter äußerer Join* bezeichnet.

Es gibt alle Zeilen aus der rechten (zweiten) Tabelle und die passenden Zeilen aus der linken (ersten) Tabelle zurück. Wenn es in der linken Tabelle keine Übereinstimmung gibt, enthält die Ergebnismenge NULL-Werte für die Spalten aus der linken Tabelle. Das Schlüsselwort OUTER kann weggelassen werden, und der Join kann einfach als RIGHT JOIN geschrieben werden. Das Gegenteil von RIGHT OUTER JOIN ist LEFT OUTER JOIN, bei dem alle Zeilen aus der linken Tabelle und die passenden Zeilen aus der rechten Tabelle zurückgegeben werden.

**Syntax:**

```
SELECT column1, column2, ..., columnn
FROM table1
RIGHT [OUTER] JOIN table2
ON table1.column = table2.column;
```

Die folgende Abfrage gibt alle Zeilen aus der Kundentabelle zusammen mit den entsprechenden Zeilen aus der Bestelltabelle zurück. Wenn ein Kunde keine Bestellungen hat, enthält das Resultset dennoch die Informationen dieses Kunden mit NULL-Werten für die Spalten order\$1id und order\$1date.

```
SELECT orders.order_id, orders.order_date, customers.customer_id, customers.name
FROM orders
RIGHT OUTER JOIN customers
ON orders.customer_id = customers.customer_id;
```

Bei der folgenden Abfrage handelt es sich um einen rechten, externen Join. Diese Abfrage gleicht LISTID-Spaltenwerte in der Tabelle LISTING (linke Tabelle) und der Tabelle SALES (rechte Tabelle) ab. Die Ergebnisse zeigen, dass LISTIDs 1, 4 und 5 den Kriterien entsprechen.

```
select listing.listid, sum(pricepaid) as price, sum(commission) as comm
from listing right outer join sales on sales.listid = listing.listid
where listing.listid between 1 and 5
group by 1
order by 1;

listid | price  |  comm
-------+--------+--------
     1 | 728.00 | 109.20
     4 |  76.00 |  11.40
     5 | 525.00 |  78.75
```

## VOLL [ÄUSSERLICH]
<a name="full-join"></a>

Gibt alle Werte aus beiden Beziehungen zurück und fügt NULL-Werte auf der Seite an, für die es keine Übereinstimmung gibt. Es wird auch als *vollständiger äußerer Join* bezeichnet. 

Es gibt alle Zeilen sowohl aus der linken als auch aus der rechten Tabelle zurück, unabhängig davon, ob eine Übereinstimmung vorliegt oder nicht. Wenn es keine Übereinstimmung gibt, enthält die Ergebnismenge NULL-Werte für die Spalten aus der Tabelle, die keine passende Zeile hat. Das Schlüsselwort OUTER kann weggelassen werden, und der Join kann einfach als FULL JOIN geschrieben werden. Der FULL OUTER JOIN wird seltener verwendet als der LEFT OUTER JOIN oder RIGHT OUTER JOIN, kann aber in bestimmten Szenarien nützlich sein, in denen Sie alle Daten aus beiden Tabellen sehen müssen, auch wenn es keine Treffer gibt.

**Syntax:**

```
SELECT column1, column2, ..., columnn
FROM table1
FULL [OUTER] JOIN table2
ON table1.column = table2.column;
```

Die folgende Abfrage gibt alle Zeilen aus den Tabellen „Kunden“ und „Bestellungen“ zurück. Wenn ein Kunde keine Bestellungen hat, enthält das Resultset dennoch die Informationen dieses Kunden mit NULL-Werten für die Spalten order\$1id und order\$1date. Wenn einer Bestellung kein Kunde zugeordnet ist, enthält das Resultset diese Bestellung mit NULL-Werten für die Spalten customer\$1id und name.

```
SELECT customers.customer_id, customers.name, orders.order_id, orders.order_date
FROM customers
FULL OUTER JOIN orders
ON customers.customer_id = orders.customer_id;
```

Bei der folgenden Abfrage handelt es sich um einen vollständigen Join. Vollständige Joins behalten die Werte aus einer der Tabellen bei, für die ein Join ausgeführt wurde, wenn in der anderen Tabelle keine Übereinstimmung gefunden wurde. Die Tabellen links und rechts werden in der Syntax als erste und zweite Tabelle aufgelistet. Es werden NULL-Werte verwendet, um die „Lücken“ im Ergebnissatz zu füllen. Diese Abfrage gleicht LISTID-Spaltenwerte in der Tabelle LISTING (linke Tabelle) und der Tabelle SALES (rechte Tabelle) ab. Die Ergebnisse zeigen, dass LISTIDs 2 und 3 zu keinen Verkäufen geführt haben.

```
select listing.listid, sum(pricepaid) as price, sum(commission) as comm
from listing full join sales on sales.listid = listing.listid
where listing.listid between 1 and 5
group by 1
order by 1;

listid | price  |  comm
-------+--------+--------
     1 | 728.00 | 109.20
     2 | NULL   | NULL
     3 | NULL   | NULL
     4 |  76.00 |  11.40
     5 | 525.00 |  78.75
```

Bei der folgenden Abfrage handelt es sich um einen vollständigen Join. Diese Abfrage gleicht LISTID-Spaltenwerte in der Tabelle LISTING (linke Tabelle) und der Tabelle SALES (rechte Tabelle) ab. Nur Zeilen, die zu keinen Verkäufen führen (LISTIDs 2 und 3), sind in den Ergebnissen enthalten.

```
select listing.listid, sum(pricepaid) as price, sum(commission) as comm
from listing full join sales on sales.listid = listing.listid
where listing.listid between 1 and 5
and (listing.listid IS NULL or sales.listid IS NULL)
group by 1
order by 1;

listid | price  |  comm
-------+--------+--------
     2 | NULL   | NULL
     3 | NULL   | NULL
```

## [LINKS] HALB
<a name="left-semi-join"></a>

Gibt Werte von der linken Seite der Tabellenreferenz zurück, die mit der rechten Seite übereinstimmen. Es wird auch als *linke Semi-Verknüpfung* bezeichnet. 

Es werden nur die Zeilen aus der linken (ersten) Tabelle zurückgegeben, für die eine entsprechende Zeile in der rechten (zweiten) Tabelle vorhanden ist. Es werden keine Spalten aus der rechten Tabelle zurückgegeben, sondern nur die Spalten aus der linken Tabelle. Der LEFT SEMI JOIN ist nützlich, wenn Sie die Zeilen in einer Tabelle suchen möchten, die eine Übereinstimmung in einer anderen Tabelle haben, ohne Daten aus der zweiten Tabelle zurückgeben zu müssen. Der LEFT SEMI JOIN ist eine effizientere Alternative zur Verwendung einer Unterabfrage mit einer IN- oder EXISTS-Klausel.

**Syntax:**

```
SELECT column1, column2, ..., columnn
FROM table1
LEFT SEMI JOIN table2
ON table1.column = table2.column;
```

Die folgende Abfrage gibt nur die Spalten customer\$1id und name aus der Kundentabelle für die Kunden zurück, die mindestens eine Bestellung in der Bestelltabelle haben. Das Resultset wird keine Spalten aus der Bestelltabelle enthalten.

```
SELECT customers.customer_id, customers.name
FROM customers
LEFT SEMI JOIN orders
ON customers.customer_id = orders.customer_id;
```

## CROSS JOIN
<a name="cross-join"></a>

Gibt das kartesische Produkt zweier Beziehungen zurück. Das bedeutet, dass die Ergebnismenge alle möglichen Kombinationen von Zeilen aus den beiden Tabellen enthält, ohne dass eine Bedingung oder ein Filter angewendet wird.

Der CROSS JOIN ist nützlich, wenn Sie alle möglichen Kombinationen von Daten aus zwei Tabellen generieren müssen, z. B. wenn Sie einen Bericht erstellen möchten, der alle möglichen Kombinationen von Kunden- und Produktinformationen anzeigt. Der CROSS JOIN unterscheidet sich von anderen Join-Typen (INNER JOIN, LEFT JOIN usw.), da er in der ON-Klausel keine Join-Bedingung enthält. Die Join-Bedingung ist für einen CROSS JOIN nicht erforderlich.

**Syntax:**

```
SELECT column1, column2, ..., columnn
FROM table1
CROSS JOIN table2;
```

Die folgende Abfrage gibt ein Resultset zurück, das alle möglichen Kombinationen von customer\$1id, customer\$1name, product\$1id und product\$1name aus den Tabellen Customers und Products enthält. Wenn die Kundentabelle 10 Zeilen und die Produkttabelle 20 Zeilen hat, enthält die Ergebnismenge von CROSS JOIN 10 x 20 = 200 Zeilen.

```
SELECT customers.customer_id, customers.name, products.product_id, products.product_name
FROM customers
CROSS JOIN products;
```

Bei der folgenden Abfrage handelt es sich um einen Cross Join oder kartesischen Join der LISTING- und der SALES-Tabelle mit einem Prädikat zur Begrenzung der Ergebnisse. Diese Abfrage entspricht den LISTID-Spaltenwerten in der SALES-Tabelle und der LISTING-Tabelle für LISTIDs 1, 2, 3, 4 und 5 in beiden Tabellen. Die Ergebnisse zeigen, dass 20 Zeilen den Kriterien entsprechen.

```
select sales.listid as sales_listid, listing.listid as listing_listid
from sales cross join listing
where sales.listid between 1 and 5
and listing.listid between 1 and 5
order by 1,2;

sales_listid | listing_listid
-------------+---------------
1            | 1
1            | 2
1            | 3
1            | 4
1            | 5
4            | 1
4            | 2
4            | 3
4            | 4
4            | 5
5            | 1
5            | 1
5            | 2
5            | 2
5            | 3
5            | 3
5            | 4
5            | 4
5            | 5
5            | 5
```

## ANTI-JOIN
<a name="anti-join"></a>

Gibt die Werte aus der linken Tabellenreferenz zurück, die nicht mit der rechten Tabellenreferenz übereinstimmen. Es wird auch als *Left Anti Join* bezeichnet.

Der ANTI JOIN ist eine nützliche Operation, wenn Sie die Zeilen in einer Tabelle suchen möchten, für die es in einer anderen Tabelle keine Übereinstimmung gibt. 

**Syntax:**

```
SELECT column1, column2, ..., columnn
FROM table1
LEFT ANTI JOIN table2
ON table1.column = table2.column;
```

Die folgende Abfrage gibt alle Kunden zurück, die keine Bestellungen aufgegeben haben.

```
SELECT customers.customer_id, customers.name
FROM customers
LEFT ANTI JOIN orders
ON customers.customer_id = orders.customer_id
WHERE orders.order_id IS NULL;
```

## NATURAL
<a name="natural-join"></a>

Gibt an, dass die Zeilen aus den beiden Beziehungen implizit auf Gleichheit für alle Spalten mit übereinstimmenden Namen abgeglichen werden. 

Es ordnet automatisch Spalten mit demselben Namen und Datentyp zwischen den beiden Tabellen zu. Sie müssen die Join-Bedingung nicht explizit in der ON-Klausel angeben. Sie kombiniert alle übereinstimmenden Spalten zwischen den beiden Tabellen in der Ergebnismenge.

NATURAL JOIN ist eine praktische Abkürzung, wenn die Tabellen, die Sie verknüpfen, Spalten mit denselben Namen und Datentypen haben. Es wird jedoch generell empfohlen, das explizitere INNER JOIN... zu verwenden ON-Syntax, um die Join-Bedingungen expliziter und verständlicher zu machen.

**Syntax:**

```
SELECT column1, column2, ..., columnn
FROM table1
NATURAL JOIN table2;
```

Das folgende Beispiel ist eine natürliche Verknüpfung zwischen zwei Tabellen mit den folgenden Spalten: `employees` `departments` 
+ `employees`Tabelle: `employee_id``first_name`,`last_name`, `department_id `
+ `departments`tabelle:`department_id`, `department_name `

Die folgende Abfrage gibt eine Ergebnismenge zurück, die den Vornamen, den Nachnamen und den Abteilungsnamen für alle übereinstimmenden Zeilen zwischen den beiden Tabellen enthält, basierend auf der `department_id` Spalte.

```
SELECT e.first_name, e.last_name, d.department_name
FROM employees e
NATURAL JOIN departments d;
```

Das folgende Beispiel ist ein NATURAL-Join zwischen zwei Tabellen. In diesem Fall haben die Spalten listid, sellerid, eventid und dateid identische Namen und Datentypen in beiden Tabellen und werden daher als Join-Spalten verwendet. Die Ergebnisse sind auf 5 Zeilen begrenzt.

```
select listid, sellerid, eventid, dateid, numtickets
from listing natural join sales
order by 1
limit 5;

listid | sellerid  | eventid | dateid | numtickets
-------+-----------+---------+--------+-----------
113    | 29704     | 4699    | 2075   | 22
115    | 39115     | 3513    | 2062   | 14
116    | 43314     | 8675    | 1910   | 28
118    | 6079      | 1611    | 1862   | 9
163    | 24880     | 8253    | 1888   | 14
```

# WHERE-Klausel
<a name="WHERE_clause"></a>

Die WHERE-Klausel enthält Bedingungen, die entweder einen Join für Tabellen ausführen oder Prädikate auf Spalten in Tabellen anwenden. Für Tabellen können interne Joins ausgeführt werden, indem entweder in der WHERE-Klausel oder in der FROM-Klausel die entsprechende Syntax verwendet wird. Die Kriterien für externe Joins müssen in der FROM-Klausel angegeben werden. 

## Syntax
<a name="WHERE_clause-synopsis"></a>

```
[ WHERE condition ]
```

## *Bedingung*
<a name="WHERE_clause-synopsis-condition"></a>

Jede Suchbedingung mit einem Booleschen Ergebnis, wie eine Join-Bedingung oder ein Prädikat für eine Tabellenspalte. In den folgenden Beispielen werden gültige Join-Bedingungen gezeigt: 

```
sales.listid=listing.listid
sales.listid<>listing.listid
```

In den folgenden Beispielen werden gültige Bedingungen für Spalten in Tabellen gezeigt: 

```
catgroup like 'S%'
venueseats between 20000 and 50000
eventname in('Jersey Boys','Spamalot')
year=2008
length(catdesc)>25
date_part(month, caldate)=6
```

Bedingungen können einfach oder komplex sein. Im Fall komplexer Bedingungen können Sie Klammern verwenden, um logische Einheiten zu isolieren. Im folgenden Beispiel wird die Join-Bedingung durch Klammern umschlossen. 

```
where (category.catid=event.catid) and category.catid in(6,7,8)
```

## Nutzungshinweise
<a name="WHERE_clause_usage_notes"></a>

Sie können in der WHERE-Klausel Aliase verwenden, um Auswahllistenausdrücke zu referenzieren. 

Sie können die Ergebnisse aggregierter Funktionen in der WHERE-Klausel nicht einschränken. Verwenden Sie für diesen Zweck die HAVING-Klausel. 

Spalten, die in der WHERE-Klausel eingeschränkt sind, müssen von Tabellenreferenzen in der FROM-Klausel abgeleitet werden. 

## Beispiel
<a name="SELECT_synopsis-example"></a>

Die folgende Abfrage verwendet eine Kombination aus verschiedenen WHERE-Klauseleinschränkungen, einschließlich einer Join-Bedingung für die Tabellen SALES und EVENT, eines Prädikats für die EVENTNAME-Spalte und zweier Prädikate für die STARTTIME-Spalte. 

```
select eventname, starttime, pricepaid/qtysold as costperticket, qtysold
from sales, event
where sales.eventid = event.eventid
and eventname='Hannah Montana'
and date_part(quarter, starttime) in(1,2)
and date_part(year, starttime) = 2008
order by 3 desc, 4, 2, 1 limit 10;

eventname    |      starttime      |   costperticket   | qtysold
----------------+---------------------+-------------------+---------
Hannah Montana | 2008-06-07 14:00:00 |     1706.00000000 |       2
Hannah Montana | 2008-05-01 19:00:00 |     1658.00000000 |       2
Hannah Montana | 2008-06-07 14:00:00 |     1479.00000000 |       1
Hannah Montana | 2008-06-07 14:00:00 |     1479.00000000 |       3
Hannah Montana | 2008-06-07 14:00:00 |     1163.00000000 |       1
Hannah Montana | 2008-06-07 14:00:00 |     1163.00000000 |       2
Hannah Montana | 2008-06-07 14:00:00 |     1163.00000000 |       4
Hannah Montana | 2008-05-01 19:00:00 |      497.00000000 |       1
Hannah Montana | 2008-05-01 19:00:00 |      497.00000000 |       2
Hannah Montana | 2008-05-01 19:00:00 |      497.00000000 |       4
(10 rows)
```

# VALUES-Klausel
<a name="VALUES"></a>

Die VALUES-Klausel wird verwendet, um eine Reihe von Zeilenwerten direkt in der Abfrage bereitzustellen, ohne dass auf eine Tabelle verwiesen werden muss. 

Die VALUES-Klausel kann in den folgenden Szenarien verwendet werden:
+ Sie können die VALUES-Klausel in einer INSERT INTO-Anweisung verwenden, um die Werte für die neuen Zeilen anzugeben, die in eine Tabelle eingefügt werden.
+ Sie können die VALUES-Klausel alleine verwenden, um eine temporäre Ergebnismenge oder eine Inline-Tabelle zu erstellen, ohne auf eine Tabelle verweisen zu müssen.
+ Sie können die VALUES-Klausel mit anderen SQL-Klauseln wie WHERE, ORDER BY oder LIMIT kombinieren, um die Zeilen in der Ergebnismenge zu filtern, zu sortieren oder einzuschränken.

Diese Klausel ist besonders nützlich, wenn Sie einen kleinen Datensatz direkt in Ihre SQL-Anweisung einfügen, abfragen oder bearbeiten müssen, ohne eine permanente Tabelle erstellen oder darauf verweisen zu müssen. Sie ermöglicht es Ihnen, die Spaltennamen und die entsprechenden Werte für jede Zeile zu definieren, sodass Sie die Flexibilität haben, temporäre Ergebnismengen zu erstellen oder Daten im laufenden Betrieb einzufügen, ohne den Aufwand, eine separate Tabelle verwalten zu müssen.

## Syntax
<a name="VALUES-syntax"></a>

```
VALUES ( expression [ , ... ] ) [ table_alias ]
```

## Parameter
<a name="VALUES-parameters"></a>

 *expression*   
Ein Ausdruck, der eine Kombination aus einem oder mehreren Werten, Operatoren und SQL-Funktionen angibt, die zu einem Wert führt.

 *table\$1alias*   
Ein Alias, der einen temporären Namen mit einer optionalen Spaltennamenliste angibt.

## Beispiel
<a name="VALUES-example"></a>

Im folgenden Beispiel wird eine Inline-Tabelle erstellt, eine temporäre tabellenähnliche Ergebnismenge mit zwei Spalten, und`col1`. `col2` Die einzelne Zeile in der Ergebnismenge enthält jeweils die Werte `"one"` und`1`. Der `SELECT * FROM` Teil der Abfrage ruft einfach alle Spalten und Zeilen aus dieser temporären Ergebnismenge ab. Die Spaltennamen (`col1`und`col2`) werden automatisch vom Datenbanksystem generiert, da die VALUES-Klausel die Spaltennamen nicht explizit spezifiziert. 

```
SELECT * FROM VALUES ("one", 1);
+----+----+
|col1|col2|
+----+----+
| one|   1|
+----+----+
```

Wenn Sie benutzerdefinierte Spaltennamen definieren möchten, können Sie dies tun, indem Sie nach der VALUES-Klausel eine AS-Klausel verwenden, etwa so:

```
SELECT * FROM (VALUES ("one", 1)) AS my_table (name, id);
+------+----+
| name | id |
+------+----+
| one  |  1 |
+------+----+
```

Dadurch würde eine temporäre Ergebnismenge mit den Spaltennamen `name` und `id` anstelle der Standardwerte `col1` und erstellt`col2`. 

# GROUP BY-Klausel
<a name="GROUP_BY_clause"></a>

Die GROUP BY-Klausel identifiziert die Gruppierungsspalten für die Abfrage. Gruppierungsspalten müssen deklariert werden, wenn die Abfrage aggregierte Werte mit Standardfunktionen wie SUM, AVG und COUNT berechnet. Wenn der SELECT-Ausdruck eine Aggregatfunktion enthält, muss jede Spalte im SELECT-Ausdruck, die sich nicht in einer Aggregatfunktion befindet, in der GROUP BY-Klausel enthalten sein.

Weitere Informationen finden Sie unter [AWS Clean Rooms Spark SQL-Funktionen](sql-functions-topic-spark.md). 

## Syntax
<a name="r_GROUP_BY_clause-syntax"></a>

```
GROUP BY group_by_clause [, ...]

group_by_clause := {
    expr |
        ROLLUP ( expr [, ...] ) |
        }
```

## *Parameter*
<a name="GROUP_BY_clause-parameters"></a>

 *expr*  
Der Liste der Spalten oder Ausdrücke muss der Liste der nicht aggregierten Ausdrücke in der Auswahlliste der Abfrage entsprechen. Betrachten Sie beispielsweise die folgende einfache Abfrage.  

```
select listid, eventid, sum(pricepaid) as revenue,
count(qtysold) as numtix
from sales
group by listid, eventid
order by 3, 4, 2, 1
limit 5;

listid | eventid | revenue | numtix
-------+---------+---------+--------
89397  |      47 |   20.00 |      1
106590 |      76 |   20.00 |      1
124683 |     393 |   20.00 |      1
103037 |     403 |   20.00 |      1
147685 |     429 |   20.00 |      1
(5 rows)
```
In dieser Abfrage besteht die Auswahlliste aus zwei aggregierten Ausdrücken. Der erste verwendet die SUM-Funktion und der zweite verwendet die COUNT-Funktion. Die übrigen beiden Spalten, LISTID und EVENTID, müssen als Gruppierungsspalten deklariert werden.  
Ausdrücke in der -Klausel können ebenfalls die Auswahlliste durch Verwendung von Ordinalzahlen referenzieren. Das vorherige Beispiel könnte beispielsweise wie folgt abgekürzt werden.  

```
select listid, eventid, sum(pricepaid) as revenue,
count(qtysold) as numtix
from sales
group by 1,2
order by 3, 4, 2, 1
limit 5;

listid | eventid | revenue | numtix
-------+---------+---------+--------
89397  |      47 |   20.00 |      1
106590 |      76 |   20.00 |      1
124683 |     393 |   20.00 |      1
103037 |     403 |   20.00 |      1
147685 |     429 |   20.00 |      1
(5 rows)
```

 *ROLLUP*   
Sie können die Aggregationserweiterung ROLLUP verwenden, um die Arbeit mehrerer GROUP BY-Operationen in einer einzigen Anweisung auszuführen. Weitere Informationen zu Aggregationserweiterungen und verwandten Funktionen finden Sie unter [Aggregationserweiterungen](GROUP_BY_aggregation-extensions.md). 

# Aggregationserweiterungen
<a name="GROUP_BY_aggregation-extensions"></a>

AWS Clean Rooms unterstützt Aggregationserweiterungen, um die Arbeit mehrerer GROUP BY-Operationen in einer einzigen Anweisung zu erledigen.

## *GROUPING SETS*
<a name="GROUP_BY_aggregation-extensions-grouping-sets"></a>

 Berechnet einen oder mehrere Gruppierungssätze in einer einzigen Anweisung. Ein Gruppierungssatz ist die Menge einer einzelnen GROUP BY-Klausel, eine Menge von 0 oder mehr Spalten, nach denen Sie die Ergebnismenge einer Abfrage gruppieren können. GROUP BY GROUPING SETS entspricht der Ausführung einer UNION ALL-Abfrage für eine Ergebnismenge, die nach verschiedenen Spalten gruppiert ist. Beispielsweise entspricht GROUP BY GROUPING SETS((a), (b)) GROUP BY a UNION ALL GROUP BY b. 

 Das folgende Beispiel gibt die Kosten der Produkte der Bestelltabelle zurück, gruppiert sowohl nach den Produktkategorien als auch nach der Art der verkauften Produkte. 

```
SELECT category, product, sum(cost) as total
FROM orders
GROUP BY GROUPING SETS(category, product);

       category       |       product        | total
----------------------+----------------------+-------
 computers            |                      |  2100
 cellphones           |                      |  1610
                      | laptop               |  2050
                      | smartphone           |  1610
                      | mouse                |    50

(5 rows)
```

## *ROLLUP*
<a name="GROUP_BY_aggregation-extensions-rollup"></a>

 Geht von einer Hierarchie aus, bei der vorangehende Spalten als übergeordnete Spalten der nachfolgenden Spalten betrachtet werden. ROLLUP gruppiert Daten nach den bereitgestellten Spalten und gibt zusätzlich zu den gruppierten Zeilen weitere Zwischensummenzeilen zurück, die die Summen auf allen Ebenen der Gruppierungsspalten darstellen. Beispielsweise können Sie GROUP BY ROLLUP((a), (b)) verwenden, um eine Ergebnismenge zurückzugeben, die zuerst nach a und dann nach b gruppiert ist, wobei angenommen wird, dass b ein Unterabschnitt von a ist. ROLLUP gibt auch eine Zeile mit der gesamten Ergebnismenge ohne Gruppierungsspalten zurück. 

GROUP BY ROLLUP((a), (b)) entspricht GROUP BY GROUPING SETS((a,b), (a), ()). 

Im folgenden Beispiel werden die Kosten der Produkte der Bestelltabelle zurückgegeben, zuerst nach Kategorie und dann nach Produkt gruppiert, wobei „product“ (Produkt) eine Unterteilung von „category“ (Kategorie) darstellt.

```
SELECT category, product, sum(cost) as total
FROM orders
GROUP BY ROLLUP(category, product) ORDER BY 1,2;

       category       |       product        | total
----------------------+----------------------+-------
 cellphones           | smartphone           |  1610
 cellphones           |                      |  1610
 computers            | laptop               |  2050
 computers            | mouse                |    50
 computers            |                      |  2100
                      |                      |  3710
(6 rows)
```

## *CUBE*
<a name="GROUP_BY_aggregation-extensions-cube"></a>

 Gruppiert Daten nach den bereitgestellten Spalten und gibt zusätzlich zu den gruppierten Zeilen weitere Zwischensummenzeilen zurück, die die Summen auf allen Ebenen der Gruppierungsspalten darstellen. CUBE gibt dieselben Zeilen wie ROLLUP zurück und fügt zusätzliche Zwischensummenzeilen für jede Kombination von Gruppierungsspalten hinzu, die nicht von ROLLUP abgedeckt wird. Beispielsweise können Sie GROUP BY CUBE ((a), (b)) verwenden, um eine Ergebnismenge zurückzugeben, die zuerst nach a und dann nach b – unter der Annahme, dass b ein Unterabschnitt von a ist – und dann nur nach b gruppiert ist. CUBE gibt auch eine Zeile mit der gesamten Ergebnismenge ohne Gruppierungsspalten zurück.

GROUP BY CUBE((a), (b)) entspricht GROUP BY GROUPING SETS((a, b), (a), (b), ()). 

Im folgenden Beispiel werden die Kosten der Produkte der Bestelltabelle zurückgegeben, zuerst nach Kategorie und dann nach Produkt gruppiert, wobei „product“ (Produkt) eine Unterteilung von „category“ (Kategorie) darstellt. Im Gegensatz zum vorherigen Beispiel für ROLLUP gibt die Anweisung Ergebnisse für jede Kombination von Gruppierungsspalten zurück. 

```
SELECT category, product, sum(cost) as total
FROM orders
GROUP BY CUBE(category, product) ORDER BY 1,2;

       category       |       product        | total
----------------------+----------------------+-------
 cellphones           | smartphone           |  1610
 cellphones           |                      |  1610
 computers            | laptop               |  2050
 computers            | mouse                |    50
 computers            |                      |  2100
                      | laptop               |  2050
                      | mouse                |    50
                      | smartphone           |  1610
                      |                      |  3710
(9 rows)
```

# HAVING-Klausel
<a name="HAVING_clause"></a>

Die HAVING-Klausel wendet eine Bedingung auf den gruppierten Zwischenergebnissatz an, den eine Abfrage zurückgibt.

## Syntax
<a name="HAVING_clause-synopsis"></a>

```
[ HAVING condition ]
```

Sie können beispielsweise die Ergebnisse einer SUM-Funktion einschränken:

```
having sum(pricepaid) >10000
```

Die HAVING-Bedingung wird angewendet, nachdem alle WHERE-Klauselbedingungen angewendet wurden und die GROUP BY-Operationen abgeschlossen sind.

Die Bedingung selbst hat das gleiche Format wie eine WHERE-Klauselbedingung.

## Nutzungshinweise
<a name="HAVING_clause_usage_notes"></a>
+ Bei jeder, in einer -Klauselbedingung referenzierten Spalte muss es sich entweder um eine Gruppierungsspalte handeln oder um eine Spalte, die sich auf das Ergebnis einer aggregierten Funktion bezieht.
+ In einer HAVING-Klausel können Sie Folgendes nicht angeben:
  + Eine Ordinalzahl, die ein Auswahllistenelement referenziert. Nur die Klauseln GROUP BY und ORDER BY akzeptieren Ordinalzahlen.

## Beispiele
<a name="HAVING_clause-examples"></a>

Die folgende Abfrage berechnet den Ticket-Gesamtverkauf für alle Veranstaltungen nach Namen. Anschließend werden Veranstaltungen entfernt, deren Gesamtverkauf weniger als 800.000 USD betrug. Die HAVING-Bedingung wird auf die Ergebnisse der Aggregierungsfunktion in der Auswahlliste angewendet: `sum(pricepaid)`.

```
select eventname, sum(pricepaid)
from sales join event on sales.eventid = event.eventid
group by 1
having sum(pricepaid) > 800000
order by 2 desc, 1;

eventname     |    sum
------------------+-----------
Mamma Mia!       | 1135454.00
Spring Awakening |  972855.00
The Country Girl |  910563.00
Macbeth          |  862580.00
Jersey Boys      |  811877.00
Legally Blonde   |  804583.00
(6 rows)
```

Die folgende Abfrage berechnet einen ähnlichen Ergebnissatz. In diesem Fall wird die HAVING-Bedingung jedoch auf ein Aggregat angewendet, das nicht in der Auswahlliste angegeben ist: `sum(qtysold)`. Veranstaltungen, für weniger als 2.000 Tickets verkauft wurden, werden aus dem Endergebnis entfernt.

```
select eventname, sum(pricepaid)
from sales join event on sales.eventid = event.eventid
group by 1
having sum(qtysold) >2000
order by 2 desc, 1;

eventname     |    sum
------------------+-----------
Mamma Mia!       | 1135454.00
Spring Awakening |  972855.00
The Country Girl |  910563.00
Macbeth          |  862580.00
Jersey Boys      |  811877.00
Legally Blonde   |  804583.00
Chicago          |  790993.00
Spamalot         |  714307.00
(8 rows)
```

# Satzoperatoren
<a name="UNION"></a>

Die *Mengenoperatoren* werden verwendet, um die Ergebnisse zweier separater Abfrageausdrücke zu vergleichen und zusammenzuführen. 

AWS Clean Rooms Spark SQL unterstützt die folgenden Mengenoperatoren, die in der folgenden Tabelle aufgeführt sind.

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/clean-rooms/latest/sql-reference/UNION.html)

Wenn Sie beispielsweise wissen möchten, welche Benutzer einer Website sowohl Käufer als auch Verkäufer sind, die Namen jedoch in getrennten Spalten oder Tabellen gespeichert sind, können Sie die *Überschneidung* zwischen diesen beiden Arten von Benutzern finden. Wenn Sie wissen möchten, welche Benutzer einer Website Käufer, jedoch nicht Verkäufer sind, können Sie den Operator EXCEPT verwenden, um den *Unterschied* zwischen diesen beiden Listen von Benutzern zu finden. Wenn Sie eine Liste aller Benutzer unabhängig von der Rolle erstellen möchten, können Sie den Operator UNION verwenden.

**Anmerkung**  
Die Klauseln ORDER BY, LIMIT, SELECT TOP und OFFSET können nicht in den Abfrageausdrücken verwendet werden, die durch die Mengenoperatoren UNION, UNION ALL, INTERSECT und EXCEPT zusammengeführt werden.

**Topics**
+ [Syntax](#UNION-synopsis)
+ [Parameters](#UNION-parameters)
+ [Reihenfolge der Evaluierung für Satzoperatoren](#UNION-order-of-evaluation-for-set-operators)
+ [Nutzungshinweise](#UNION-usage-notes)
+ [Beispiel für UNION-Abfragen](example_union_query.md)
+ [Beispiel für die UNION ALL-Abfrage](example_unionall_query.md)
+ [Beispiel für INTERSECT-Abfragen](example_intersect_query.md)
+ [Beispiel für die EXCEPT-Abfrage](Example_EXCEPT_query.md)

## Syntax
<a name="UNION-synopsis"></a>

```
subquery1
{ { UNION [ ALL | DISTINCT ] |
              INTERSECT [ ALL | DISTINCT ] |
              EXCEPT [ ALL | DISTINCT ] } subquery2 } [...] }
```

## Parameters
<a name="UNION-parameters"></a>

 *Unterabfrage1, Unterabfrage2*   
Ein Abfrageausdruck, der in Form seiner Auswahlliste einem zweiten Abfrageausdruck entspricht, der auf den Operator UNION, UNION ALL, INTERSECT, INTERSECT ALL, EXCEPT oder EXCEPT ALL folgt. Die beiden Ausdrücke müssen die gleiche Zahl von Ausgabespalten mit kompatiblen Datentypen enthalten. Andernfalls können die beiden Ergebnissätze nicht verglichen und zusammengeführt werden. Mengenoperationen ermöglichen keine implizite Konvertierung zwischen verschiedenen Kategorien von Datentypen. Weitere Informationen finden Sie unter [Kompatibilität von Typen und Umwandlung zwischen Typen](s_Type_conversion.md).  
Sie können Abfragen erstellen, die eine unbegrenzte Anzahl von Abfrageausdrücken enthalten, und sie mithilfe der Operatoren UNION, INTERSECT und EXCEPT in beliebigen Kombinationen verbinden. Beispielsweise ist die folgende Abfragestruktur gültig, wenn die Tabellen T1, T2 und T3 kompatible Sätze von Spalten enthalten:   

```
select * from t1
union
select * from t2
except
select * from t3
```

VEREINIGUNG [ALLE \$1 UNTERSCHIEDLICH]  
Satzoperation, die Zeilen aus zwei Abfrageausdrücken zurückgibt, unabhängig davon, ob die Zeilen von einem oder von beiden Ausdrücken abgeleitet werden.

SICH ÜBERSCHNEIDEN [ALLE \$1 UNTERSCHIEDLICH]  
Satzoperation, die Zeilen zurückgibt, die von zwei Abfrageausdrücken abgeleitet werden. Zeilen, die nicht von beiden Ausdrücken zurückgegeben werden, werden verworfen.

AUSSER [ALLE \$1 UNTERSCHIEDLICH]  
Satzoperation, die Zeilen zurückgibt, die von einem von zwei Abfrageausdrücken abgeleitet werden. Um sich für das Ergebnis zu qualifizieren, dürfen Zeilen zwar in der ersten Ergebnistabelle, nicht jedoch in der zweiten vorhanden sein.   
EXCEPT ALL entfernt keine Duplikate aus den Ergebniszeilen.  
MINUS und EXCEPT sind exakte Synonyme. 

## Reihenfolge der Evaluierung für Satzoperatoren
<a name="UNION-order-of-evaluation-for-set-operators"></a>

Die Satzoperatoren UNION und EXCEPT sind links-assoziativ. Wenn keine Klammern angegeben werden, um die Reihenfolge zu beeinflussen, wird eine Kombination dieser Satzoperatoren von links nach rechts ausgewertet. Beispielsweise wird in der folgenden Abfrage der Operator UNION von T1 und T2 zuerst ausgewertet. Anschließend wird die Operation EXCEPT für das UNION-Ergebnis ausgeführt: 

```
select * from t1
union
select * from t2
except
select * from t3
```

Der Operator INTERSECT hat Vorrang vor den Operatoren UNION und EXCEPT, wenn in derselben Abfrage eine Kombination von Operatoren verwendet wird. Beispielsweise wird in der folgenden Abfrage die Schnittmenge von T2 und T3 ausgewertet und anschließend mit T1 vereinigt: 

```
select * from t1
union
select * from t2
intersect
select * from t3
```

Durch die Hinzufügung von Klammern können Sie eine andere Reihenfolge für die Auswertung erzwingen. Im folgenden Fall wird für das Ergebnis von UNION für T1 und T2 eine Überschneidung mit T3 ausgewertet. Die Abfrage führt wahrscheinlich zu einem anderen Ergebnis. 

```
(select * from t1
union
select * from t2)
intersect
(select * from t3)
```

## Nutzungshinweise
<a name="UNION-usage-notes"></a>
+ Die Spaltennamen, die im Ergebnis einer Satzoperationsabfrage zurückgegeben werden, sind die Spaltennamen (Spaltenaliase) aus den Tabellen im ersten Abfrageausdruck. Da diese Spaltennamen potenziell irreführend sein können, da die Werte in der Spalte aus Tabellen auf beiden Seiten des Satzoperators abgeleitet werden, sollten Sie möglicherweise sinnvolle Aliase für den Ergebnissatz bereitstellen.
+ Wenn Abfragen mit Satzoperatoren Dezimalergebnisse zurückgeben, geben die entsprechenden Ergebnisspalten Werte mit derselben Genauigkeit und Skalierung zurück. In der folgenden Abfrage, in der T1.REVENUE eine DECIMAL(10,2)-Spalte ist und T2.REVENUE eine DECIMAL(8,4)-Spalte ist, ist das Dezimalergebnis DECIMAL(12,4): 

  ```
  select t1.revenue union select t2.revenue;
  ```

  Die Skalierung ist `4`, da dies die maximale Skalierung der beiden Spalten ist. Die Genauigkeit ist `12`, da T1.REVENUE 8 Stellen links vom Dezimalkomma erfordert (12 – 4 = 8). Dieser Vorgang stellt sicher, dass alle Werte aus beiden Seiten der UNION-Operation in das Ergebnis passen. Für 64-Bit-Werte ist die maximale Ergebnisgenauigkeit 19 und die maximale Ergebnisskalierung 18. Für 128-Bit-Werte ist die maximale Ergebnisgenauigkeit 38 und die maximale Ergebnisskalierung 37.

  Wenn der resultierende Datentyp die AWS Clean Rooms Genauigkeits- und Skalierungsgrenzen überschreitet, gibt die Abfrage einen Fehler zurück.
+ Bei Satzoperationen werden zwei Zeilen als identisch behandelt, wenn für jedes korrespondierendes Spaltenpaar die beiden Datenwerte beide *gleich* oder beide *NULL* sind. Wenn beispielsweise die Tabellen T1 und T2 beide nur eine Spalte und eine Zeile enthalten und diese Zeile in beiden Tabellen NULL ist, gibt eine INTERSECT-Operation für diese Tabellen diese Zeile zurück.

# Beispiel für UNION-Abfragen
<a name="example_union_query"></a>

In der folgenden UNION-Abfrage werden Zeilen in der Tabelle SALES mit Zeilen in der Tabelle LISTING zusammengeführt. Aus jeder Tabelle werden drei kompatible Spalten ausgewählt. In diesem Fall haben die korrespondierenden Spalten die gleichen Namen und Datentypen. 

```
select listid, sellerid, eventid from listing
union select listid, sellerid, eventid from sales


listid | sellerid | eventid
--------+----------+---------
1 |    36861 |    7872
2 |    16002 |    4806
3 |    21461 |    4256
4 |     8117 |    4337
5 |     1616 |    8647
```

Das folgende Beispiel zeigt, wie Sie der Ausgabe einer UNION-Abfrage einen Literalwert hinzufügen können, um zu sehen, durch welche Abfrageausdrücke die einzelnen Zeilen im Ergebnissatz jeweils generiert wurden. Die Abfrage identifiziert Zeilen aus dem ersten Abfrageausdruck als „B“ (für Käufer) und Zeilen aus dem zweiten Abfrageausdruck als „S“ (für Verkäufer). 

Die Abfrage identifiziert Käufer und Verkäufer für Tickettransaktionen, die einen Wert von mindestens 10.000 USD haben. Der einzige Unterschied zwischen den beiden Abfrageausdrücken auf beiden Seiten des UNION-Operators besteht in der Joining-Spalte für die Tabelle SALES. 

```
select listid, lastname, firstname, username,
pricepaid as price, 'S' as buyorsell
from sales, users
where sales.sellerid=users.userid
and pricepaid >=10000
union
select listid, lastname, firstname, username, pricepaid,
'B' as buyorsell
from sales, users
where sales.buyerid=users.userid
and pricepaid >=10000

listid | lastname | firstname | username |   price   | buyorsell
--------+----------+-----------+----------+-----------+-----------
209658 | Lamb     | Colette   | VOR15LYI |  10000.00 | B
209658 | West     | Kato      | ELU81XAA |  10000.00 | S
212395 | Greer    | Harlan    | GXO71KOC |  12624.00 | S
212395 | Perry    | Cora      | YWR73YNZ |  12624.00 | B
215156 | Banks    | Patrick   | ZNQ69CLT |  10000.00 | S
215156 | Hayden   | Malachi   | BBG56AKU |  10000.00 | B
```

Das folgende Beispiel verwendet einen UNION ALL-Operator, da duplizierte Zeilen im Ergebnis beibehalten werden müssen, wenn gefunden. Für eine bestimmte Reihe von Ereignissen IDs gibt die Abfrage 0 oder mehr Zeilen für jeden Verkauf zurück, der mit jedem Ereignis verknüpft ist, und 0 oder 1 Zeile für jede Auflistung dieses Ereignisses. Ereignisse IDs sind für jede Zeile in den Tabellen LISTING und EVENT eindeutig, aber es kann mehrere Verkäufe für dieselbe Kombination aus Ereignis und Angebot IDs in der Tabelle SALES geben. 

Die dritte Spalte im Ergebnissatz identifiziert die Quelle der Zeile. Wenn sie aus der Tabelle SALES stammt, wird sie in der Spalte SALESROW mit „Ja“ markiert. (SALESROW ist ein Alias für SALES.LISTID.) Wenn sie aus der Tabelle LISTING stammt, wird sie in der Spalte SALESROW mit „Nein“ markiert. 

In diesem Fall besteht der Ergebnissatz aus drei Verkaufszeilen für Auflistung 500, Ereignis 7787. Mit anderen Worten, für diese Kombination von Auflistung und Ereignis fanden drei verschiedene Transaktionen statt. Bei den anderen beiden Auflistungen, 501 und 502, wurden keine Verkäufe erzielt. Daher IDs stammt die einzige Zeile, die die Abfrage für diese Listen generiert, aus der Tabelle LISTING (SALESROW = 'No'). 

```
select eventid, listid, 'Yes' as salesrow
from sales
where listid in(500,501,502)
union all
select eventid, listid, 'No'
from listing
where listid in(500,501,502)

eventid | listid | salesrow
---------+--------+----------
7787 |    500 | No
7787 |    500 | Yes
7787 |    500 | Yes
7787 |    500 | Yes
6473 |    501 | No
5108 |    502 | No
```

Wenn Sie die gleiche Abfrage ohne das Schlüsselwort ALL ausführen, gibt das Ergebnis nur eine der Verkaufstransaktionen zurück. 

```
select eventid, listid, 'Yes' as salesrow
from sales
where listid in(500,501,502)
union
select eventid, listid, 'No'
from listing
where listid in(500,501,502)

eventid | listid | salesrow
---------+--------+----------
7787 |    500 | No
7787 |    500 | Yes
6473 |    501 | No
5108 |    502 | No
```

# Beispiel für die UNION ALL-Abfrage
<a name="example_unionall_query"></a>

Das folgende Beispiel verwendet einen UNION ALL-Operator, da duplizierte Zeilen im Ergebnis beibehalten werden müssen, wenn gefunden. Für eine bestimmte Reihe von Ereignissen IDs gibt die Abfrage 0 oder mehr Zeilen für jeden Verkauf zurück, der mit jeder Veranstaltung verknüpft ist, und 0 oder 1 Zeile für jede Auflistung dieser Veranstaltung. Ereignisse IDs sind für jede Zeile in den Tabellen LISTING und EVENT eindeutig, aber es kann mehrere Verkäufe für dieselbe Kombination aus Ereignis und Angebot IDs in der Tabelle SALES geben.

Die dritte Spalte im Ergebnissatz identifiziert die Quelle der Zeile. Wenn sie aus der Tabelle SALES stammt, wird sie in der Spalte SALESROW mit „Ja“ markiert. (SALESROW ist ein Alias für SALES.LISTID.) Wenn sie aus der Tabelle LISTING stammt, wird sie in der Spalte SALESROW mit „Nein“ markiert.

In diesem Fall besteht der Ergebnissatz aus drei Verkaufszeilen für Auflistung 500, Ereignis 7787. Mit anderen Worten, für diese Kombination von Auflistung und Ereignis fanden drei verschiedene Transaktionen statt. Bei den anderen beiden Auflistungen, 501 und 502, wurden keine Verkäufe erzielt. Daher IDs stammt die einzige Zeile, die die Abfrage für diese Listen generiert, aus der Tabelle LISTING (SALESROW = 'No').

```
select eventid, listid, 'Yes' as salesrow
from sales
where listid in(500,501,502)
union all
select eventid, listid, 'No'
from listing
where listid in(500,501,502)

eventid | listid | salesrow
---------+--------+----------
7787 |    500 | No
7787 |    500 | Yes
7787 |    500 | Yes
7787 |    500 | Yes
6473 |    501 | No
5108 |    502 | No
```

Wenn Sie die gleiche Abfrage ohne das Schlüsselwort ALL ausführen, gibt das Ergebnis nur eine der Verkaufstransaktionen zurück. 

```
select eventid, listid, 'Yes' as salesrow
from sales
where listid in(500,501,502)
union
select eventid, listid, 'No'
from listing
where listid in(500,501,502)
eventid | listid | salesrow
---------+--------+----------
7787 |    500 | No
7787 |    500 | Yes
6473 |    501 | No
5108 |    502 | No
```

# Beispiel für INTERSECT-Abfragen
<a name="example_intersect_query"></a>

Vergleichen Sie das folgende Beispiel mit dem ersten UNION-Beispiel. Der einzige Unterschied zwischen den beiden Beispielen besteht im verwendeten Satzoperator. Die Ergebnisse unterscheiden sich jedoch stark. Nur eine Zeile ist identisch: 

```
235494 |    23875 |    8771
```

 Dies ist die einzige Zeile im begrenzten Ergebnis von 5 Zeilen, die in beiden Tabellen gefunden wurde.

```
select listid, sellerid, eventid from listing
intersect
select listid, sellerid, eventid from sales

listid | sellerid | eventid
--------+----------+---------
235494 |    23875 |    8771
235482 |     1067 |    2667
235479 |     1589 |    7303
235476 |    15550 |     793
235475 |    22306 |    7848
```

Die folgende Abfrage sucht Veranstaltungen (für die Tickets verkauft wurden), die im März sowohl in New York City als auch in Los Angeles stattfanden. Der Unterschied zwischen den beiden Abfrageausdrücken auf beiden Seiten des UNION-Operators besteht in der Einschränkung für die Spalte VENUECITY.

```
select distinct eventname from event, sales, venue
where event.eventid=sales.eventid and event.venueid=venue.venueid
and date_part(month,starttime)=3 and venuecity='Los Angeles'
intersect
select distinct eventname from event, sales, venue
where event.eventid=sales.eventid and event.venueid=venue.venueid
and date_part(month,starttime)=3 and venuecity='New York City';

eventname
----------------------------
A Streetcar Named Desire
Dirty Dancing
Electra
Running with Annalise
Hairspray
Mary Poppins
November
Oliver!
Return To Forever
Rhinoceros
South Pacific
The 39 Steps
The Bacchae
The Caucasian Chalk Circle
The Country Girl
Wicked
Woyzeck
```

# Beispiel für die EXCEPT-Abfrage
<a name="Example_EXCEPT_query"></a>

Die CATEGORY-Tabelle in der Datenbank enthält die folgenden 11 Zeilen: 

```
 catid | catgroup |  catname  |                  catdesc
-------+----------+-----------+--------------------------------------------
   1   | Sports   | MLB       | Major League Baseball
   2   | Sports   | NHL       | National Hockey League
   3   | Sports   | NFL       | National Football League
   4   | Sports   | NBA       | National Basketball Association
   5   | Sports   | MLS       | Major League Soccer
   6   | Shows    | Musicals  | Musical theatre
   7   | Shows    | Plays     | All non-musical theatre
   8   | Shows    | Opera     | All opera and light opera
   9   | Concerts | Pop       | All rock and pop music concerts
  10   | Concerts | Jazz      | All jazz singers and bands
  11   | Concerts | Classical | All symphony, concerto, and choir concerts
(11 rows)
```

Angenommen, eine Tabelle namens CATEGORY\$1STAGE (eine Staging-Tabelle) enthält eine einzige zusätzliche Zeile: 

```
 catid | catgroup |  catname  |                  catdesc
-------+----------+-----------+--------------------------------------------
   1   | Sports   | MLB       | Major League Baseball
   2   | Sports   | NHL       | National Hockey League
   3   | Sports   | NFL       | National Football League
   4   | Sports   | NBA       | National Basketball Association
   5   | Sports   | MLS       | Major League Soccer
   6   | Shows    | Musicals  | Musical theatre
   7   | Shows    | Plays     | All non-musical theatre
   8   | Shows    | Opera     | All opera and light opera
   9   | Concerts | Pop       | All rock and pop music concerts
  10   | Concerts | Jazz      | All jazz singers and bands
  11   | Concerts | Classical | All symphony, concerto, and choir concerts
  12   | Concerts | Comedy    | All stand up comedy performances
(12 rows)
```

Gibt den Unterschied zwischen den beiden Tabellen zurück. Mit anderen Worten, gibt Zeilen zurück, die in der Tabelle CATEGORY\$1STAGE, jedoch nicht in der Tabelle CATEGORY enthalten sind: 

```
select * from category_stage
except
select * from category;

catid | catgroup | catname |             catdesc
-------+----------+---------+----------------------------------
  12  | Concerts | Comedy  | All stand up comedy performances
(1 row)
```

Die folgende gleichwertige Abfrage verwendet das Synonym MINUS. 

```
select * from category_stage
minus
select * from category;

catid | catgroup | catname |             catdesc
-------+----------+---------+----------------------------------
  12  | Concerts | Comedy  | All stand up comedy performances
(1 row)
```

Wenn Sie die Reihenfolge der SELECT-Ausdrücke umkehren, gibt die Abfrage keine Zeilen zurück. 

# ORDER BY-Klausel
<a name="ORDER_BY_clause"></a>

Die ORDER BY-Klausel sortiert den Ergebnissatz einer Abfrage.

**Anmerkung**  
Der äußerste ORDER BY-Ausdruck darf nur Spalten enthalten, die sich in der Auswahlliste befinden.

**Topics**
+ [Syntax](#ORDER_BY_clause-synopsis)
+ [Parameters](#ORDER_BY_clause-parameters)
+ [Nutzungshinweise](#ORDER_BY_usage_notes)
+ [Beispiele mit ORDER BY](Examples_with_ORDER_BY.md)

## Syntax
<a name="ORDER_BY_clause-synopsis"></a>

```
[ ORDER BY expression [ ASC | DESC ] ]
[ NULLS FIRST | NULLS LAST ]
[ LIMIT { count | ALL } ]
[ OFFSET start ]
```

## Parameters
<a name="ORDER_BY_clause-parameters"></a>

 *expression*   
Ausdruck, der die Sortierreihenfolge des Abfrageergebnisses definiert. Er besteht aus einer oder mehreren Spalten in der Auswahlliste. Die Ergebnisse werden auf der Basis einer binären UTF-8-Reihenfolge zurückgegeben. Sie können auch Folgendes angeben:  
+ Ordinalzahlen, die die Position der Auswahllisteneinträge darstellen (oder die Position der Spalten in der Tabelle, wenn keine Auswahlliste vorhanden ist)
+ Aliase, die Auswahllisteneinträge definieren
Wenn die -Klausel mehrere Ausdrücke enthält, wird der Ergebnissatz nach dem ersten Ausdruck sortiert. Anschließend wird der zweite Ausdruck auf Zeilen mit übereinstimmenden Werten aus dem ersten Ausdruck angewendet usw.

ASC \$1 DESC   
Eine Option, die die Sortierreihenfolge für den Ausdruck wie folgt definiert:   
+ ASC: aufsteigend (beispielsweise niedrig nach hoch für numerische Werte und A bis Z für Zeichenfolgen). Wenn keine Option angegeben wird, werden die Daten standardmäßig in aufsteigender Reihenfolge sortiert. 
+ DESC: absteigend (beispielsweise hoch nach niedrig für numerische Werte und Z bis A für Zeichenfolgen). 

NULLS FIRST \$1 NULLS LAST  
Option, die angibt, ob NULL-Werte vor Nicht-Null-Werten oder nach Nicht-Null-Werten aufgelistet werden sollen. Standardmäßig werden NULL-Werte in einer ASC-Reihenfolge an letzter Stelle sortiert und aufgeführt und in einer DESC-Reihenfolge an erster Stelle sortiert und aufgeführt.

LIMIT *number* \$1 ALL   <a name="order-by-clause-limit"></a>
Option, die die Anzahl der sortierten Zeilen steuert, die von der Abfrage zurückgegeben werden. Bei der LIMIT-Zahl muss es sich um eine positive Ganzzahl handeln. Der maximal zulässige Wert ist `2147483647`.   
LIMIT 0 gibt keine Zeilen zurück. Sie können diese Syntax für Testzwecke verwenden: um zu prüfen, ob eine Abfrage ausgeführt wird (ohne Zeilen anzuzeigen) oder um eine Spaltenliste aus einer Tabelle zurückzugeben. Eine -Klausel ist redundant, wenn Sie LIMIT 0 verwenden, um eine Spaltenliste zurückzugeben. Der Standardwert ist LIMIT ALL. 

OFFSET *start*   <a name="order-by-clause-offset"></a>
Option, die die Anzahl der Zeilen vor *start* angibt, die übersprungen werden sollen, bevor Zeilen zurückgegeben werden. Bei der OFFSET-Zahl muss es sich um eine positive Ganzzahl handeln. Der maximal zulässige Wert ist `2147483647`. Bei der Verwendung mit der Option LIMIT werden OFFSET-Zeilen übersprungen, bevor die Zahl der LIMIT-Zeilen gezählt werden, die zurückgegeben werden. Wenn die LIMIT-Option nicht verwendet wird, wird die Zahl der Zeilen im Ergebnissatz um die Zahl der übersprungenen Zeilen reduziert. Die von einer OFFSET-Klausel übersprungenen Zeilen müssen dennoch gescannt werden. Daher ist es möglicherweise ineffizient, einen großen OFFSET-Wert zu verwenden.

## Nutzungshinweise
<a name="ORDER_BY_usage_notes"></a>

 Beachten Sie das folgende erwartete Verhalten bei Verwendung von ORDER BY-Klauseln: 
+ NULL-Werte gelten als „höher“ als alle anderen Werte. Bei Verwendung der standardmäßigen aufsteigenden Sortierfolge befinden sich NULL-Werte am Ende. Um dieses Verhalten zu ändern, wählen Sie die Option NULLS FIRST.
+ Wenn eine Anfrage keine ORDER BY-Klausel enthält, gibt das System Ergebnissätze ohne vorhersagbare Anordnung der Zeilen zurück. Wenn dieselbe Abfrage zweimal ausgeführt wird, wird der Ergebnissatz möglicherweise in einer anderen Reihenfolge zurückgegeben. 
+ Die Optionen LIMIT und OFFSET können ohne ORDER BY-Klausel verwendet werden. Um jedoch einen konsistenten Satz von Zeilen zurückzugeben, verwenden Sie diese Optionen in Verbindung mit ORDER BY. 
+ In jedem parallel System AWS Clean Rooms, wenn ORDER BY keine eindeutige Reihenfolge erzeugt, ist die Reihenfolge der Zeilen nicht deterministisch. Das heißt, wenn der ORDER BY-Ausdruck doppelte Werte erzeugt, kann die Reihenfolge, in der diese Zeilen zurückgegeben werden, von anderen Systemen oder von einem Lauf AWS Clean Rooms zum nächsten variieren. 
+ AWS Clean Rooms unterstützt keine Zeichenkettenliterale in ORDER BY-Klauseln.

# Beispiele mit ORDER BY
<a name="Examples_with_ORDER_BY"></a>

Gibt alle 11 Zeilen aus der Tabelle CATEGORY geordnet nach der zweiten Spalte, CATGROUP, zurück. Ergebnisse, die denselben CATGROUP-Wert haben, ordnen die CATDESC-Spaltenwerte nach der Länge der Zeichenfolge. Dann wird nach Spalten CATID und CATNAME geordnet. 

```
select * from category order by 2, 1, 3;

catid | catgroup |  catname  |                  catdesc
-------+----------+-----------+----------------------------------------
10 | Concerts | Jazz      | All jazz singers and bands
9 | Concerts | Pop       | All rock and pop music concerts
11 | Concerts | Classical | All symphony, concerto, and choir conce
6 | Shows    | Musicals  | Musical theatre
7 | Shows    | Plays     | All non-musical theatre
8 | Shows    | Opera     | All opera and light opera
5 | Sports   | MLS       | Major League Soccer
1 | Sports   | MLB       | Major League Baseball
2 | Sports   | NHL       | National Hockey League
3 | Sports   | NFL       | National Football League
4 | Sports   | NBA       | National Basketball Association
(11 rows)
```

Gibt ausgewählte Spalten aus der Tabelle SALES zurück, geordnet nach den höchsten QTYSOLD-Werten. Begrenzt das Ergebnis auf die obersten 10 Zeilen: 

```
select salesid, qtysold, pricepaid, commission, saletime from sales
order by qtysold, pricepaid, commission, salesid, saletime desc

salesid | qtysold | pricepaid | commission |      saletime
---------+---------+-----------+------------+---------------------
15401 |       8 |    272.00 |      40.80 | 2008-03-18 06:54:56
61683 |       8 |    296.00 |      44.40 | 2008-11-26 04:00:23
90528 |       8 |    328.00 |      49.20 | 2008-06-11 02:38:09
74549 |       8 |    336.00 |      50.40 | 2008-01-19 12:01:21
130232 |       8 |    352.00 |      52.80 | 2008-05-02 05:52:31
55243 |       8 |    384.00 |      57.60 | 2008-07-12 02:19:53
16004 |       8 |    440.00 |      66.00 | 2008-11-04 07:22:31
489 |       8 |    496.00 |      74.40 | 2008-08-03 05:48:55
4197 |       8 |    512.00 |      76.80 | 2008-03-23 11:35:33
16929 |       8 |    568.00 |      85.20 | 2008-12-19 02:59:33
```

Gibt unter Verwendung der LIMIT 0-Syntax eine Spaltenliste, aber keine Zeilen zurück: 

```
select * from venue limit 0;
venueid | venuename | venuecity | venuestate | venueseats
---------+-----------+-----------+------------+------------
(0 rows)
```

# Beispiele für Unterabfragen
<a name="Subquery_examples"></a>

In den folgenden Beispielen zeigen verschiedene Möglichkeiten, wie Unterabfragen in SELECT-Abfragen integriert werden können. Ein weiteres Beispiel für die Verwendung von Unterabfragen finden Sie unter [Beispiel](join-clause.md#Join_examples). 

## Unterabfragen in der SELECT-Liste
<a name="Subquery_examples-select-list-subquery"></a>

Das folgende Beispiel enthält eine Unterabfrage in der SELECT-Liste. Diese Unterabfrage ist *skalar*: Sie gibt nur eine Spalte und einen Wert zurück. Dies wird im Ergebnis für jede Zeile wiederholt, die von der umschließenden Abfrage zurückgegeben wird. Die Abfrage vergleicht den von der Unterabfrage berechneten Q1SALES-Wert mit den Verkaufswerten für zwei andere Quartale (2 und 3) im Jahr 2008 wie von der umschließenden Abfrage definiert. 

```
select qtr, sum(pricepaid) as qtrsales,
(select sum(pricepaid)
from sales join date on sales.dateid=date.dateid
where qtr='1' and year=2008) as q1sales
from sales join date on sales.dateid=date.dateid
where qtr in('2','3') and year=2008
group by qtr
order by qtr;

qtr  |  qtrsales   |   q1sales
-------+-------------+-------------
2     | 30560050.00 | 24742065.00
3     | 31170237.00 | 24742065.00
(2 rows)
```

## Unterabfragen in der WHERE-Klausel
<a name="Subquery_examples-where-clause-subquery"></a>

Das folgende Beispiel enthält eine Tabellenunterabfrage in der WHERE-Klausel. Diese Unterabfrage produziert mehrere Zeilen. In diesem Fall enthalten die Zeilen nur eine Spalte. Tabellenunterabfragen können jedoch mehrere Spalten und Zeilen enthalten, genau wie jede andere Tabelle. 

Die Abfrage sucht die 10 Top-Verkäufer in Bezug die meisten verkauften Tickets. Die Liste der Top 10 wird durch die Unterabfrage eingeschränkt, die Benutzer entfernt, die in Städten mit Ticketverkaufsstellen leben. Diese Abfrage kann auf verschiedene Arten geschrieben werden. Beispielsweise könnte die Unterabfrage als ein Join innerhalb der Hauptabfrage geschrieben werden. 

```
select firstname, lastname, city, max(qtysold) as maxsold
from users join sales on users.userid=sales.sellerid
where users.city not in(select venuecity from venue)
group by firstname, lastname, city
order by maxsold desc, city desc
limit 10;

firstname | lastname  |      city      | maxsold
-----------+-----------+----------------+---------
Noah       | Guerrero | Worcester      |       8
Isadora    | Moss     | Winooski       |       8
Kieran     | Harrison | Westminster    |       8
Heidi      | Davis    | Warwick        |       8
Sara       | Anthony  | Waco           |       8
Bree       | Buck     | Valdez         |       8
Evangeline | Sampson  | Trenton        |       8
Kendall    | Keith    | Stillwater     |       8
Bertha     | Bishop   | Stevens Point  |       8
Patricia   | Anderson | South Portland |       8
(10 rows)
```

## Unterabfragen in der WITH-Klausel
<a name="Subquery_examples-with-clause-subqueries"></a>

Siehe [WITH-Klausel](WITH_clause.md). 

# Korrelierte Unterabfragen
<a name="correlated_subqueries"></a>

Das folgende Beispiel enthält eine *korrelierte Unterabfrage* in der WHERE-Klausel. Diese Art von Unterabfrage enthält mindestens eine Korrelation zwischen ihren Spalten und den Spalten, die von der umschließenden Abfrage produziert werden. In diesem Fall ist die Korrelation `where s.listid=l.listid`. Die Unterabfrage wird für jede Zeile ausgeführt, die die umschließende Abfrage produziert, um die Zeile zu qualifizieren oder zu disqualifizieren. 

```
select salesid, listid, sum(pricepaid) from sales s
where qtysold=
(select max(numtickets) from listing l
where s.listid=l.listid)
group by 1,2
order by 1,2
limit 5;

salesid | listid |   sum
--------+--------+----------
 27     |     28 | 111.00
 81     |    103 | 181.00
 142    |    149 | 240.00
 146    |    152 | 231.00
 194    |    210 | 144.00
(5 rows)
```

## Muster für korrelierte Unterabfragen, die nicht unterstützt werden
<a name="correlated_subqueries-correlated-subquery-patterns-that-are-not-supported"></a>

Der Abfrageplaner verwendet eine Methode für das Neuschreiben von Abfragen, die als Entkorrelierung von Unterabfragen bezeichnet wird, um verschiedene Muster korrelierter Unterabfragen für die Ausführung in einer MPP-Umgebung zu optimieren. Einige Typen von korrelierten Unterabfragen folgen Mustern, die nicht korreliert AWS Clean Rooms werden können und auch nicht unterstützt werden. Abfragen, die die folgenden Korrelierungsreferenzen enthalten, geben Fehler zurück: 
+  Korrelierungsreferenzen, die einen Abfrageblock überspringen, auch als „überspringende Korrelierungsreferenzen“ bekannt. Beispielsweise sind in der folgenden Abfrage der Block mit der Korrelierungsreferenz und der übersprungene Block durch ein NOT EXISTS-Prädikat verbunden: 

  ```
  select event.eventname from event
  where not exists
  (select * from listing
  where not exists
  (select * from sales where event.eventid=sales.eventid));
  ```

  Der übersprungende Block ist in diesem Fall die Unterabfrage für die LISTING-Tabelle. Die Korrelierungsreferenz korreliert die Tabellen EVENT und SALES. 
+  Korrelierungsreferenzen aus einer Unterabfrage, die Teil einer ON-Klausel in einer externen Abfrage ist: 

  ```
  select * from category
  left join event
  on category.catid=event.catid and eventid =
  (select max(eventid) from sales where sales.eventid=event.eventid);
  ```

  Die ON-Klausel enthält eine Korrelierungsreferenz aus SALES in der Unterabfrage für EVENT in der umschließenden Abfrage. 
+ Korrelationsreferenzen, die auf Null reagieren, auf eine Systemtabelle. AWS Clean Rooms Beispiel: 

  ```
  select attrelid
  from my_locks sl, my_attribute
  where sl.table_id=my_attribute.attrelid and 1 not in
  (select 1 from my_opclass where sl.lock_owner = opcowner);
  ```
+ Korrelierungsreferenzen aus einer Unterabfrage, die eine Fensterfunktion enthält. 

  ```
  select listid, qtysold
  from sales s
  where qtysold not in
  (select sum(numtickets) over() from listing l where s.listid=l.listid);
  ```
+ Referenzen in einer GROUP BY-Spalte zu den Ergebnissen einer korrelierten Unterabfrage. Beispiel: 

  ```
  select listing.listid,
  (select count (sales.listid) from sales where sales.listid=listing.listid) as list
  from listing
  group by list, listing.listid;
  ```
+ Korrelierungsreferenzen aus einer Unterabfrage mit einer Aggregationsfunktion und einer GROUP BY-Klausel, die durch ein IN-Prädikat mit der umschließenden Abfrage verbunden sind. (Diese Einschränkung gilt nicht für die Aggregationsfunktionen MIN und MAX.) Beispiel: 

  ```
  select * from listing where listid in
  (select sum(qtysold)
  from sales
  where numtickets>4
  group by salesid);
  ```