

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

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

Il comando SELECT restituisce righe da tabelle e funzioni definite dall'utente.

I seguenti comandi, clausole e operatori di set SELECT SQL sono supportati in AWS Clean Rooms Spark SQL:

**Topics**
+ [SELECT list](sql-function-select-list-spark.md)
+ [Clausola WITH](WITH_clause.md)
+ [Clausola FROM](FROM_clause30.md)
+ [Clausola JOIN](join-clause.md)
+ [Clausola WHERE](WHERE_clause.md)
+ [clausola VALUES](VALUES.md)
+ [Clausola GROUP BY](GROUP_BY_clause.md)
+ [Clausola HAVING](HAVING_clause.md)
+ [Operatori su set](UNION.md)
+ [Clausola ORDER BY](ORDER_BY_clause.md)
+ [Esempi di sottoquery](Subquery_examples.md)
+ [Sottoquery correlate](correlated_subqueries.md)

La sintassi, gli argomenti e alcuni esempi provengono da [Apache](https://spark.apache.org/docs/latest/api/sql/) Spark SQL Reference.

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

I SELECT list nomi delle colonne, delle funzioni e delle espressioni che vuoi che la query restituisca. L'elenco rappresenta l'output della query.

## Sintassi
<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  
Opzione che elimina le righe duplicate dal set di risultati, in base ai valori corrispondenti in una o più colonne.

*expression*  
Espressione formata da una o più colonne presenti nelle tabelle a cui fa riferimento la query. Un'espressione può contenere funzioni SQL. Esempio:

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

AS column\$1alias

Nome temporaneo per la colonna che viene utilizzata nel set di risultati finale. La AS parola chiave è facoltativa. Esempio:

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

Se non specifichi un alias per un'espressione che non è un semplice nome di colonna, il set di risultati applica un nome predefinito a quella colonna.

**Nota**  
L'alias viene riconosciuto subito dopo essere stato definito nell'elenco di destinazione. Non è possibile utilizzare un alias in altre espressioni definite successivamente nello stesso elenco di destinazione. 

# Clausola WITH
<a name="WITH_clause"></a>

Una clausola WITH è una clausola facoltativa che precede l'elenco SELECT in una query. La clausola WITH definisce uno o più *common\$1table\$1expression*. Ogni espressione comune di tabella (CTE) definisce una tabella temporanea, che è simile a una definizione di vista. È possibile fare riferimento a queste tabelle temporanee nella clausola FROM. Vengono utilizzati solo durante l'esecuzione della query a cui appartengono. Ogni CTE nella clausola WITH specifica un nome di tabella, un elenco facoltativo di nomi di colonna e un'espressione di query che restituisce una tabella (un'istruzione SELECT).

Le sottoquery della clausola WITH sono un modo efficace per definire le tabelle che possono essere utilizzate durante l'esecuzione di una singola query. In ogni caso, è possibile ottenere gli stessi risultati utilizzando le sottoquery nel corpo principale dell'istruzione SELECT, ma le sottoquery della clausola WITH potrebbero essere più semplici da scrivere e leggere. Ove possibile, le sottoquery della clausola WITH che sono referenziate più volte sono ottimizzate come sottoespressioni comuni; vale a dire, potrebbe essere possibile valutare una sottoquery WITH una volta e riutilizzarne i risultati. Tieni presente che le sottoespressioni comuni non sono limitate a quelle definite nella clausola WITH.

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

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

dove *common\$1table\$1expression può* essere non ricorsivo. Di seguito è riportata la forma non ricorsiva: 

```
CTE_table_name AS ( query )
```

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

 *common\$1table\$1expression*   
Definisce una tabella temporanea a cui è possibile fare riferimento nella [Clausola FROM](FROM_clause30.md) e viene utilizzato solo durante l'esecuzione della query a cui appartiene. 

 *CTE\$1table\$1name*   
Nome univoco per una tabella temporanea che definisce i risultati di una sottoquery della clausola WITH. Non puoi utilizzare nomi duplicati in una singola clausola WITH. A ogni sottoquery deve essere assegnato un nome di tabella a cui è possibile fare riferimento nella [Clausola FROM](FROM_clause30.md).

 *query*   
 Qualsiasi query SELECT AWS Clean Rooms che supporti. Per informazioni, consulta [SELECT](sql-commands-select-spark.md). 

## Note per l'utilizzo
<a name="WITH_clause-usage-notes"></a>

È possibile utilizzare una clausola WITH nella seguente istruzione SQL: 
+ SELECT, WITH, UNION, UNION ALL, INTERSECT, INTERSECT ALL, EXCEPT o EXCEPT ALL 

Se la clausola FROM di una query che contiene una clausola WITH non fa riferimento a nessuna delle tabelle definite dalla clausola WITH, la clausola WITH viene ignorata e la query viene eseguita normalmente.

A una tabella definita da una sottoquery della clausola WITH è possibile fare riferimento solo nell'ambito della query SELECT avviata dalla clausola WITH. Ad esempio, puoi fare riferimento a una tabella di questo tipo nella clausola FROM di una sottoquery nell'elenco SELECT, nella clausola WHERE o nella clausola HAVING. Non puoi utilizzare una clausola WITH in una sottoquery e fare riferimento alla tabella nella clausola FROM della query principale o un'altra sottoquery. Questo modello di query genera un messaggio di errore nel formato `relation table_name doesn't exist` per la tabella della clausola WITH.

Non puoi specificare un'altra clausola WITH all'interno di una sottoquery della clausola WITH.

Non puoi creare riferimenti alle tabelle definite dalle sottoquery della clausola WITH. Ad esempio, la seguente query restituisce un errore a causa del riferimento in avanti alla tabella W2 nella definizione della tabella W1: 

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

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

L'esempio seguente mostra il caso più semplice possibile di una query che contiene una clausola WITH. La query WITH denominata VENUECOPY seleziona tutte le righe dalla tabella VENUE. La query principale a sua volta seleziona tutte le righe da VENUECOPY. La tabella VENUECOPY esiste solo per la durata di questa query. 

```
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)
```

L'esempio seguente mostra una clausola WITH che produce due tabelle, denominate VENUE\$1SALES e TOP\$1VENUES. La seconda tabella della query WITH seleziona dalla prima. A sua volta, la clausola WHERE del blocco di query principale contiene una sottoquery che vincola la tabella TOP\$1VENUES. 

```
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)
```

I seguenti due esempi illustrano le regole per l'ambito dei riferimenti di tabella basati sulle sottoquery della clausola WITH. La prima query viene eseguita, ma la seconda non riesce con un errore previsto. La prima query contiene la sottoquery clausola WITH all'interno dell'elenco SELECT della query principale. Alla tabella definita dalla clausola WITH (HOLIDAYS) si fa riferimento nella clausola FROM della sottoquery nell'elenco SELECT: 

```
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)
```

La seconda query non riesce perché tenta di fare riferimento alla tabella HOLIDAYS nella query principale e nella sottoquery elenco SELECT. I riferimenti della query principale sono fuori ambito. 

```
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
```

# Clausola FROM
<a name="FROM_clause30"></a>

La clausola FROM in una query elenca i riferimenti di tabella (tabelle, viste e sottoquery) da cui vengono selezionati i dati. Se sono elencati più riferimenti tabella, è necessario unire le tabelle, utilizzando la sintassi appropriata nella clausola FROM o nella clausola WHERE. Se non vengono specificati criteri di join, il sistema elabora la query come cross-join (prodotto cartesiano). 

**Topics**
+ [Sintassi](#FROM_clause30-synopsis)
+ [Parameters](#FROM_clause30-parameters)
+ [Note per l'utilizzo](#FROM_clause_usage_notes)

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

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

dove *table\$1reference* è una delle opzioni seguenti: 

```
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*   
Tabella definita da una sottoquery nella [Clausola WITH](WITH_clause.md). 

 *table\$1name*   
Nome di una tabella o vista. 

 *alias*   
Nome alternativo temporaneo per una tabella o vista. L'alias è obbligatorio per una tabella derivata da una sottoquery. In altri riferimenti di tabella, gli alias sono facoltativi. La AS parola chiave è sempre facoltativa. Gli alias di tabella forniscono una comoda scelta rapida per identificare le tabelle in altre parti di una query, come nella clausola WHERE.   
Esempio:   

```
select * from sales s, listing l
where s.listid=l.listid
```
Se si definisce un alias di tabella, è necessario utilizzare l'alias per fare riferimento a quella tabella nella query.   
Ad esempio, se la query è`SELECT "tbl"."col" FROM "tbl" AS "t"`, la query fallirebbe perché ora il nome della tabella viene sostanzialmente sovrascritto. Una query valida in questo caso sarebbe. `SELECT "t"."col" FROM "tbl" AS "t"`

 *column\$1alias*   
Un'espressione semplice che restituisce un valore. 

 *subquery*   
Espressione della query che restituisce una tabella. La tabella esiste solo per la durata della query e in genere le viene assegnato un nome o un *alias*; tuttavia l'alias non è obbligatorio. Puoi anche definire i nomi delle colonne per le tabelle che derivano da sottoquery. L'assegnazione degli alias alle colonne è importante quando vuoi unire i risultati delle sottoquery ad altre tabelle e quando vuoi selezionare o vincolare tali colonne altrove nella query.   
Una sottoquery può contenere una clausola ORDER BY, ma questa potrebbe non avere alcun effetto se non viene specificata una clausola LIMIT o OFFSET. 

NATURAL   
Definisce un join che utilizza automaticamente tutte le coppie di colonne con lo stesso nome nelle due tabelle come colonne di unione. La condizione di join esplicita non è obbligatoria. Ad esempio, se le tabelle CATEGORY ed EVENT hanno entrambe le colonne denominate CATID, un join naturale di tali tabelle è un join sulle rispettive colonne CATID.   
Se viene specificato un join NATURAL ma non esistono coppie di colonne con nome identico nelle tabelle da unire, la query viene impostata automaticamente su un cross-join. 

 *join\$1type*   
Specifica uno dei seguenti tipi di join:   
+ [INNER] JOIN 
+ LEFT [OUTER] JOIN 
+ RIGHT [OUTER] JOIN 
+ FULL [OUTER] JOIN 
+ CROSS JOIN 
I cross-join sono join non qualificati; restituiscono il prodotto cartesiano delle due tabelle.   
I join inner e outer sono join qualificati. Sono qualificati in modo implicito (in join naturali) con la sintassi ON o USING nella clausola FROM o con una condizione della clausola WHERE.   
Un inner join restituisce solo le righe corrispondenti, in base alla condizione di join o all'elenco delle colonne di join. Un outer join restituisce tutte le righe che l'inner join equivalente restituirebbe, più le righe non corrispondenti dalla tabella "left", dalla tabella "right" o da entrambe le tabelle. La tabella di sinistra è la tabella elencata per prima e la tabella di destra è la seconda tabella nell'elenco. Le righe non corrispondenti contengono valori NULL per riempire gli spazi vuoti nelle colonne di output. 

ON *join\$1condition*   
Tipo di specifica del join in cui le colonne di unione vengono dichiarate come una condizione che segue la parola chiave ON. Ad esempio:   

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

USING ( *join\$1column* [, ...] )   
Tipo di specifica del join in cui le colonne di unione vengono elencate tra parentesi. Se vengono specificate più colonne di unione, queste sono delimitate da virgole. La parola chiave USING deve precedere l'elenco. Ad esempio:   

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

## Note per l'utilizzo
<a name="FROM_clause_usage_notes"></a>

Le colonne di unione devono avere tipi di dati comparabili. 

Un join NATURAL o USING conserva solo una di ciascuna coppia di colonne di unione nel set di risultati intermedi. 

Un join con la sintassi ON mantiene entrambe le colonne di unione nel set di risultati intermedi. 

consultare anche [Clausola WITH](WITH_clause.md). 

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

Una clausola SQL JOIN viene utilizzata per combinare i dati di due o più tabelle in base a campi comuni. I risultati potrebbero cambiare o meno a seconda del metodo di join specificato. Gli outer join sinistro e destro mantengono i valori da una delle tabelle unite quando non viene trovata alcuna corrispondenza nell'altra tabella. 

La combinazione del tipo JOIN e della condizione di join determina quali righe vengono incluse nel set di risultati finale. Le clausole SELECT e WHERE controllano quindi quali colonne vengono restituite e come vengono filtrate le righe. Comprendere i diversi tipi di JOIN e come utilizzarli in modo efficace è un'abilità fondamentale in SQL, perché consente di combinare i dati di più tabelle in modo flessibile e potente.

## Sintassi
<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>

 *SELEZIONA colonna1, colonna2,..., colonnaN*   
Le colonne da includere nel set di risultati. È possibile selezionare le colonne da una o entrambe le tabelle coinvolte nel JOIN. 

 *DALLA tabella 1*   
La prima tabella (a sinistra) dell'operazione JOIN.

 *[JOIN \$1 INNER JOIN \$1 LEFT [OUTER] JOIN \$1 RIGHT [OUTER] JOIN \$1 [OUTER] JOIN COMPLETO] table2:*   
Il tipo di JOIN da eseguire. JOIN o INNER JOIN restituisce solo le righe con valori corrispondenti in entrambe le tabelle.   
LEFT [OUTER] JOIN restituisce tutte le righe della tabella di sinistra, con le righe corrispondenti della tabella di destra.   
RIGHT [OUTER] JOIN restituisce tutte le righe della tabella di destra, con le righe corrispondenti della tabella di sinistra.   
FULL [OUTER] JOIN restituisce tutte le righe di entrambe le tabelle, indipendentemente dal fatto che esista una corrispondenza o meno.   
CROSS JOIN crea un prodotto cartesiano delle righe delle due tabelle.

 *ON table1.column = table2.column*   
La condizione di unione, che specifica come vengono abbinate le righe nelle due tabelle. La condizione di unione può essere basata su una o più colonne.

 *Condizione WHERE:*   
Una clausola facoltativa che può essere utilizzata per filtrare ulteriormente il set di risultati, in base a una condizione specificata. 

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

Di seguito è riportato un esempio di join tra due tabelle con la clausola USING. In questo caso, le colonne listid e eventid vengono utilizzate come colonne di join. I risultati sono limitati a cinque righe.

```
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
```

# Tipi di join
<a name="join-types"></a>

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

Questo è il tipo di join predefinito. Restituisce le righe con valori corrispondenti in entrambi i riferimenti alla tabella. 

L'INNER JOIN è il tipo di join più comune utilizzato in SQL. È un modo efficace per combinare i dati di più tabelle in base a una colonna o un set di colonne comune. 

**Sintassi:**

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

La seguente query restituirà tutte le righe in cui è presente un valore customer\$1id corrispondente tra le tabelle clienti e ordini. Il set di risultati conterrà le colonne customer\$1id, name, order\$1id e order\$1date.

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

La seguente query è un inner join (senza la parola chiave JOIN) tra la tabella LISTING e la tabella SALES, in cui il LISTID della tabella LISTING è compreso tra 1 e 5. Questa query corrisponde ai valori della colonna LISTID nella tabella LISTING (la tabella di sinistra) e SALES (la tabella di destra). I risultati mostrano che LISTID 1, 4 e 5 corrispondono ai criteri.

```
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
```

Di seguito è riportato un esempio di inner join con la clausola ON. In questo caso, le righe NULL non vengono restituite.

```
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
```

La seguente query è un inner join di due sottoquery della clausola FROM. La query trova il numero di biglietti venduti e invenduti per diverse categorie di eventi (concerti e spettacoli). Queste sottoquery della clausola FROM sono sottoquery *table* e possono restituire più colonne e righe.

```
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
```

## SINISTRA [ESTERNO]
<a name="left-outer-join"></a>

Restituisce tutti i valori dal riferimento alla tabella sinistra e i valori corrispondenti dal riferimento alla tabella destra oppure aggiunge NULL se non c'è corrispondenza. Viene anche chiamato *left* outer join. 

Restituisce tutte le righe della tabella sinistra (prima) e le righe corrispondenti della tabella destra (seconda). Se non c'è alcuna corrispondenza nella tabella di destra, il set di risultati conterrà valori NULL per le colonne della tabella di destra. La parola chiave OUTER può essere omessa e il join può essere scritto semplicemente come LEFT JOIN. L'opposto di un LEFT OUTER JOIN è un RIGHT OUTER JOIN, che restituisce tutte le righe della tabella di destra e le righe corrispondenti della tabella di sinistra.

**Sintassi:**

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

La seguente query restituirà tutte le righe della tabella clienti, insieme alle righe corrispondenti della tabella ordini. Se un cliente non ha ordini, il set di risultati includerà comunque le informazioni del cliente, con valori NULL per le colonne order\$1id e 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;
```

La seguente query è un outer join. Gli outer join sinistro e destro mantengono i valori da una delle tabelle unite quando non viene trovata alcuna corrispondenza nell'altra tabella. Le tabelle sinistra e destra sono la prima e la seconda tabella elencate nella sintassi. I valori NULL vengono utilizzati per riempire gli "spazi vuoti" nel set di risultati. Questa query corrisponde ai valori della colonna LISTID nella tabella LISTING (la tabella di sinistra) e SALES (la tabella di destra). I risultati mostrano che LISTIDs 2 e 3 non hanno portato ad alcuna vendita.

```
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
```

## DESTRA [ESTERNO]
<a name="right-outer-join"></a>

Restituisce tutti i valori dal riferimento alla tabella destra e i valori corrispondenti dal riferimento alla tabella sinistra oppure aggiunge NULL se non c'è corrispondenza. Viene anche chiamato *right* outer join.

Restituisce tutte le righe della tabella destra (seconda) e le righe corrispondenti della tabella sinistra (prima). Se non c'è alcuna corrispondenza nella tabella a sinistra, il set di risultati conterrà valori NULL per le colonne della tabella di sinistra. La parola chiave OUTER può essere omessa e il join può essere scritto semplicemente come RIGHT JOIN. L'opposto di un RIGHT OUTER JOIN è un LEFT OUTER JOIN, che restituisce tutte le righe della tabella di sinistra e le righe corrispondenti della tabella di destra.

**Sintassi:**

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

La seguente query restituirà tutte le righe della tabella clienti, insieme alle righe corrispondenti della tabella ordini. Se un cliente non ha ordini, il set di risultati includerà comunque le informazioni del cliente, con valori NULL per le colonne order\$1id e 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;
```

La seguente query è un outer join. Questa query corrisponde ai valori della colonna LISTID nella tabella LISTING (la tabella di sinistra) e SALES (la tabella di destra). I risultati mostrano che LISTIDs 1, 4 e 5 corrispondono ai criteri.

```
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
```

## COMPLETO [ESTERNO]
<a name="full-join"></a>

Restituisce tutti i valori di entrambe le relazioni, aggiungendo valori NULL sul lato che non corrisponde. Viene anche chiamato join *esterno completo*. 

Restituisce tutte le righe delle tabelle sinistra e destra, indipendentemente dal fatto che esista una corrispondenza o meno. Se non c'è alcuna corrispondenza, il set di risultati conterrà valori NULL per le colonne della tabella che non hanno una riga corrispondente. La parola chiave OUTER può essere omessa e il join può essere scritto semplicemente come FULL JOIN. Il FULL OUTER JOIN è usato meno comunemente rispetto al LEFT OUTER JOIN o al RIGHT OUTER JOIN, ma può essere utile in alcuni scenari in cui è necessario visualizzare tutti i dati di entrambe le tabelle, anche se non ci sono corrispondenze.

**Sintassi:**

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

La seguente query restituirà tutte le righe delle tabelle clienti e ordini. Se un cliente non ha ordini, il set di risultati includerà comunque le informazioni del cliente, con valori NULL per le colonne order\$1id e order\$1date. Se a un ordine non è associato alcun cliente, il set di risultati includerà quell'ordine, con valori NULL per le colonne customer\$1id e 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;
```

La seguente query è un fullr join. I full join mantengono i valori da una delle tabelle unite quando non viene trovata alcuna corrispondenza nell'altra tabella. Le tabelle sinistra e destra sono la prima e la seconda tabella elencate nella sintassi. I valori NULL vengono utilizzati per riempire gli "spazi vuoti" nel set di risultati. Questa query corrisponde ai valori della colonna LISTID nella tabella LISTING (la tabella di sinistra) e SALES (la tabella di destra). I risultati mostrano che LISTIDs 2 e 3 non hanno portato ad alcuna vendita.

```
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
```

La seguente query è un full join. Questa query corrisponde ai valori della colonna LISTID nella tabella LISTING (la tabella di sinistra) e SALES (la tabella di destra). Nei risultati vengono visualizzate solo le righe che non generano vendite (LISTIDs 2 e 3).

```
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
```

## [SINISTRA] SEMI
<a name="left-semi-join"></a>

Restituisce i valori dal lato sinistro del riferimento alla tabella che corrisponde a quello destro. Viene anche chiamato *left semi join*. 

Restituisce solo le righe della tabella sinistra (prima) che hanno una riga corrispondente nella tabella destra (seconda). Non restituisce alcuna colonna della tabella di destra, ma solo le colonne della tabella di sinistra. Il LEFT SEMI JOIN è utile quando si desidera trovare le righe di una tabella che hanno una corrispondenza in un'altra tabella, senza dover restituire alcun dato dalla seconda tabella. Il LEFT SEMI JOIN è un'alternativa più efficiente all'utilizzo di una sottoquery con una clausola IN o EXISTS.

**Sintassi:**

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

La seguente query restituirà solo le colonne customer\$1id e name della tabella customers, per i clienti che hanno almeno un ordine nella tabella ordini. Il set di risultati non includerà alcuna colonna della tabella degli ordini.

```
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>

Restituisce il prodotto cartesiano di due relazioni. Ciò significa che il set di risultati conterrà tutte le possibili combinazioni di righe delle due tabelle, senza applicare alcuna condizione o filtro.

Il CROSS JOIN è utile quando è necessario generare tutte le possibili combinazioni di dati da due tabelle, ad esempio nel caso di creazione di un report che mostri tutte le possibili combinazioni di informazioni sui clienti e sui prodotti. Il CROSS JOIN è diverso dagli altri tipi di join (INNER JOIN, LEFT JOIN, ecc.) perché non ha una condizione di join nella clausola ON. La condizione di unione non è richiesta per un CROSS JOIN.

**Sintassi:**

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

La seguente query restituirà un set di risultati che contiene tutte le possibili combinazioni di customer\$1id, customer\$1name, product\$1id e product\$1name dalle tabelle clienti e prodotti. Se la tabella clienti ha 10 righe e la tabella prodotti ha 20 righe, il set di risultati di CROSS JOIN conterrà 10 x 20 = 200 righe.

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

La seguente query è un cross join o un join cartesiano della tabella LISTING e della tabella SALES con un predicato per limitare i risultati. Questa query corrisponde ai valori delle colonne LISTID nella tabella SALES e nella tabella LISTING per LISTIDs 1, 2, 3, 4 e 5 in entrambe le tabelle. I risultati mostrano che 20 righe soddisfano i criteri.

```
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>

Restituisce i valori del riferimento alla tabella sinistra che non corrispondono al riferimento alla tabella destra. Viene anche chiamato *antijoin sinistro*.

L'ANTI JOIN è un'operazione utile quando si desidera trovare le righe di una tabella che non hanno una corrispondenza in un'altra tabella. 

**Sintassi:**

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

La seguente query restituirà tutti i clienti che non hanno effettuato ordini.

```
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>

Speciifica che le righe delle due relazioni verranno associate implicitamente in termini di uguaglianza per tutte le colonne con nomi corrispondenti. 

Abbina automaticamente le colonne con lo stesso nome e tipo di dati tra le due tabelle. Non richiede di specificare esplicitamente la condizione di unione nella clausola ON. Combina tutte le colonne corrispondenti tra le due tabelle nel set di risultati.

NATURAL JOIN è una comoda abbreviazione quando le tabelle che stai unendo hanno colonne con gli stessi nomi e tipi di dati. Tuttavia, in genere si consiglia di utilizzare il più esplicito INNER JOIN... Sintassi ON per rendere le condizioni di unione più esplicite e facili da capire.

**Sintassi:**

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

L'esempio seguente è un'unione naturale tra due tabelle `employees` e`departments`, con le seguenti colonne: 
+ `employees`tabella: `employee_id``first_name`,`last_name`, `department_id `
+ `departments`tavolo:`department_id`, `department_name `

La seguente query restituirà un set di risultati che include il nome, il cognome e il nome del reparto per tutte le righe corrispondenti tra le due tabelle, in base alla `department_id` colonna.

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

Di seguito è riportato un esempio di join naturale tra due tabelle. In questo caso, le colonne listid, sellerid, eventid e dateid hanno nomi e tipi di dati identici in entrambe le tabelle e quindi vengono utilizzate come colonne di join. I risultati sono limitati a cinque righe.

```
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
```

# Clausola WHERE
<a name="WHERE_clause"></a>

La clausola WHERE contiene le condizioni che possono unire tabelle o applicare predicati alle colonne nelle tabelle. Le tabelle possono inner join utilizzando la sintassi appropriata nella clausola WHERE o nella clausola FROM. I criteri degli outer join devono essere specificati nella clausola FROM. 

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

```
[ WHERE condition ]
```

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

Qualsiasi condizione di ricerca con un risultato booleano, ad esempio una condizione di join o un predicato su una colonna della tabella. I seguenti esempi sono condizioni di join valide: 

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

I seguenti esempi sono condizioni valide sulle colonne delle tabelle: 

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

Le condizioni possono essere semplici o complesse; per le condizioni complesse, puoi utilizzare le parentesi per isolare le unità logiche. Nell'esempio seguente, la condizione di join è racchiusa tra parentesi. 

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

## Note per l'utilizzo
<a name="WHERE_clause_usage_notes"></a>

Puoi utilizzare gli alias nella clausola WHERE per fare riferimento alle espressioni di elenco selezionate. 

Non puoi limitare i risultati delle funzioni di aggregazione nella clausola WHERE; utilizza la clausola HAVING per questo scopo. 

Le colonne che sono limitate nella clausola WHERE devono derivare dai riferimenti di tabella nella clausola FROM. 

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

La seguente query utilizza una combinazione di diverse restrizioni della clausola WHERE, inclusa una condizione di join per le tabelle SALES ed EVENT, un predicato sulla colonna EVENTNAME e due predicati sulla colonna STARTTIME. 

```
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)
```

# clausola VALUES
<a name="VALUES"></a>

La clausola VALUES viene utilizzata per fornire un set di valori di riga direttamente nella query, senza la necessità di fare riferimento a una tabella. 

La clausola VALUES può essere utilizzata nei seguenti scenari:
+ È possibile utilizzare la clausola VALUES in un'istruzione INSERT INTO per specificare i valori per le nuove righe da inserire in una tabella.
+ È possibile utilizzare la clausola VALUES da sola per creare un set di risultati temporaneo o una tabella in linea, senza la necessità di fare riferimento a una tabella.
+ È possibile combinare la clausola VALUES con altre clausole SQL, ad esempio WHERE, ORDER BY o LIMIT, per filtrare, ordinare o limitare le righe del set di risultati.

Questa clausola è particolarmente utile quando è necessario inserire, interrogare o manipolare un piccolo set di dati direttamente nell'istruzione SQL, senza la necessità di creare o fare riferimento a una tabella permanente. Consente di definire i nomi delle colonne e i valori corrispondenti per ogni riga, offrendovi la flessibilità necessaria per creare set di risultati temporanei o inserire dati all'istante, senza il sovraccarico dovuto alla gestione di una tabella separata.

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

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

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

 *espressione*   
Un'espressione che specifica una combinazione di uno o più valori, operatori e funzioni SQL che restituisce un valore.

 *table\$1alias*   
Un alias che specifica un nome temporaneo con un elenco di nomi di colonna opzionale.

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

L'esempio seguente crea una tabella in linea, un set di risultati temporaneo simile a una tabella con due colonne e. `col1` `col2` La singola riga del set di risultati contiene i valori `"one"` e`1`, rispettivamente. La `SELECT * FROM` parte della query recupera semplicemente tutte le colonne e le righe da questo set di risultati temporaneo. I nomi delle colonne (`col1`and`col2`) vengono generati automaticamente dal sistema di database, poiché la clausola VALUES non specifica esplicitamente i nomi delle colonne. 

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

Se desideri definire nomi di colonna personalizzati, puoi farlo utilizzando una clausola AS dopo la clausola VALUES, in questo modo:

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

Ciò creerebbe un set di risultati temporaneo con i nomi delle colonne `name` e`id`, invece del valore predefinito `col1` e. `col2` 

# Clausola GROUP BY
<a name="GROUP_BY_clause"></a>

La clausola GROUP BY identifica le colonne di raggruppamento per la query. Le colonne di raggruppamento devono essere dichiarate quando la query calcola gli aggregati con le funzioni standard, ad esempio SUM, AVG e COUNT. Se nell'espressione SELECT è presente una funzione di aggregazione, qualsiasi colonna dell'espressione SELECT che non si trova in una funzione aggregata deve essere inclusa nella clausola GROUP BY.

Per ulteriori informazioni, consulta [AWS Clean Rooms Funzioni Spark SQL](sql-functions-topic-spark.md). 

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

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

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

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

 *expr*  
L'elenco di colonne o espressioni deve corrispondere all'elenco di espressioni non aggregate dell'elenco di selezione della query. A titolo illustrativo, prendi in considerazione la query semplice riportata di seguito.  

```
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 questa query, l'elenco di selezione è composto da due espressioni di aggregazione. La prima utilizza la funzione SUM e la seconda utilizza la funzione COUNT. Le restanti due colonne, LISTID ed EVENTID, devono essere dichiarate come colonne di raggruppamento.  
Le espressioni nella clausola GROUP BY possono anche fare riferimento all'elenco di selezione usando numeri ordinali. A titolo illustrativo, l'esempio precedente potrebbe essere abbreviato come segue.  

```
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*   
È possibile utilizzare l'estensione di aggregazione ROLLUP per eseguire il lavoro di più operazioni GROUP BY in un'unica istruzione. Per ulteriori informazioni sulle estensioni di aggregazione e sulle funzioni correlate, consulta [Estensioni di aggregazione](GROUP_BY_aggregation-extensions.md). 

# Estensioni di aggregazione
<a name="GROUP_BY_aggregation-extensions"></a>

AWS Clean Rooms supporta le estensioni di aggregazione per eseguire il lavoro di più operazioni GROUP BY in un'unica istruzione.

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

 Calcola uno o più set di raggruppamento in una singola istruzione. Un set di raggruppamento è l'insieme di una singola clausola GROUP BY, un set di 0 o più colonne in base al quale è possibile raggruppare il set di risultati di una query. GROUP BY GROUPING SETS equivale all'esecuzione di una query UNION ALL su un set di risultati raggruppato in colonne diverse. Ad esempio, GROUP BY GROUP SETS((a), (b)) è equivalente a GROUP BY a UNION ALL GROUP BY b. 

 L'esempio seguente restituisce il costo dei prodotti nella tabella degli ordini raggruppati in base alle categorie dei prodotti e al tipo di prodotti venduti. 

```
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>

 Presuppone una gerarchia in cui le colonne precedenti sono considerate le colonne padri delle colonne successive. ROLLUP raggruppa i dati in base alle colonne fornite, restituendo righe di subtotali aggiuntive che rappresentano i totali in tutti i livelli di colonne di raggruppamento, oltre alle righe raggruppate. Ad esempio, puoi utilizzare GROUP BY ROLLUP((a), (b)) per restituire un set di risultati raggruppato prima per a, poi per b supponendo che b sia una sottosezione di a. ROLLUP restituisce anche una riga con l'intero set di risultati senza colonne di raggruppamento. 

GROUP BY ROLLUP((a), (b)) è equivalente a GROUP BY GROUPING SETS((a,b), (a), ()). 

L'esempio seguente restituisce il costo dei prodotti nella tabella degli ordini raggruppati prima per categoria e poi per prodotto, con product come sezione della categoria.

```
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>

 Raggruppa i dati in base alle colonne fornite, restituendo righe di subtotali aggiuntive che rappresentano i totali in tutti i livelli di colonne di raggruppamento, oltre alle righe raggruppate. CUBE restituisce le stesse righe di ROLLUP, ma aggiunge ulteriori righe di subtotali per ogni combinazione di colonne di raggruppamento non previste da ROLLUP. Ad esempio, è possibile utilizzare GROUP BY CUBE((a), (b)) per restituire un set di risultati raggruppato prima per a, poi per b, supponendo che b sia una sottosezione di a, quindi solo per b. CUBE restituisce anche una riga con l'intero set di risultati senza colonne di raggruppamento.

GROUP BY CUBE((a), (b)) è equivalente a GROUP BY GROUPING SETS((a, b), (a), (b), ()). 

L'esempio seguente restituisce il costo dei prodotti nella tabella degli ordini raggruppati prima per categoria e poi per prodotto, con product come sezione della categoria. A differenza dell'esempio precedente per ROLLUP, l'istruzione restituisce risultati per ogni combinazione di colonne di raggruppamento. 

```
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)
```

# Clausola HAVING
<a name="HAVING_clause"></a>

La clausola HAVING applica una condizione al set di risultati raggruppati intermedi restituiti da una query.

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

```
[ HAVING condition ]
```

Ad esempio, puoi limitare i risultati di una funzione SUM:

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

La condizione HAVING viene applicata dopo che tutte le condizioni della clausola WHERE sono state applicate e le operazioni GROUP BY sono state completate.

La condizione stessa assume lo stesso formato di qualsiasi condizione della clausola WHERE.

## Note per l'utilizzo
<a name="HAVING_clause_usage_notes"></a>
+ Qualsiasi colonna a cui viene fatto riferimento in una condizione della clausola HAVING deve essere una colonna di raggruppamento o una colonna che fa riferimento al risultato di una funzione di aggregazione.
+ In una clausola HAVING, non è possibile specificare:
  + Un numero ordinale che fa riferimento a una voce di elenco selezionata. Solo le clausole GROUP BY e ORDER BY accettano numeri ordinali.

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

La seguente query calcola le vendite totali dei biglietti per tutti gli eventi in base al nome, quindi elimina gli eventi in cui le vendite totali erano inferiori a \$1800.000. La condizione HAVING viene applicata ai risultati della funzione di aggregazione nell'elenco di selezione: `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)
```

La seguente query calcola un set di risultati simile. In questo caso, tuttavia, la condizione HAVING viene applicata a un'aggregazione che non è specificata nell'elenco di selezione: `sum(qtysold)`. Gli eventi che non hanno venduto più di 2.000 biglietti sono stati eliminati dal risultato finale.

```
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)
```

# Operatori su set
<a name="UNION"></a>

*Gli operatori set* vengono utilizzati per confrontare e unire i risultati di due espressioni di query separate. 

AWS Clean Rooms Spark SQL supporta i seguenti operatori di set elencati nella tabella seguente.

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

Ad esempio, se vuoi sapere quali utenti di un sito web sono sia acquirenti che venditori ma i loro nomi utente sono memorizzati in colonne o tabelle separate, puoi trovare *l'intersezione* di questi due tipi di utenti. Se vuoi sapere quali utenti del sito sono acquirenti ma non venditori, puoi utilizzare l'operatore EXCEPT per trovare la *difference* tra i due elenchi di utenti. Se vuoi creare l'elenco di tutti gli utenti, indipendentemente dal ruolo, puoi utilizzare l'operatore UNION.

**Nota**  
Le clausole ORDER BY, LIMIT, SELECT TOP e OFFSET non possono essere utilizzate nelle espressioni di query unite dagli operatori di set UNION, UNION ALL, INTERSECT e EXCEPT.

**Topics**
+ [Sintassi](#UNION-synopsis)
+ [Parameters](#UNION-parameters)
+ [Ordine di valutazione degli operatori di definizione](#UNION-order-of-evaluation-for-set-operators)
+ [Note per l'utilizzo](#UNION-usage-notes)
+ [Query UNION di esempio](example_union_query.md)
+ [Query UNION ALL di esempio](example_unionall_query.md)
+ [Query INTERSECT di esempio](example_intersect_query.md)
+ [Query EXCEPT di esempio](Example_EXCEPT_query.md)

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

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

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

 *subquery1, subquery2*   
Un'espressione di query che corrisponde, sotto forma di elenco di selezione, a una seconda espressione di query che segue l'operatore UNION, UNION ALL, INTERSECT, INTERSECT ALL, EXCEPT o EXCEPT ALL. Le due espressioni devono contenere lo stesso numero di colonne di output con tipi di dati compatibili; in caso contrario, i due set di risultati non possono essere confrontati e uniti. Le operazioni di set non consentono la conversione implicita tra diverse categorie di tipi di dati. Per ulteriori informazioni, consulta [Conversione e compatibilità dei tipi](s_Type_conversion.md).  
Puoi creare query contenenti un numero illimitato di espressioni di query e collegarle agli operatori UNION, INTERSECT ed EXCEPT in qualsiasi combinazione. Ad esempio, la seguente struttura di query è valida, assumendo che le tabelle T1, T2 e T3 contengano set di colonne compatibili:   

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

UNIONE [TUTTI \$1 DISTINTI]  
Operazione di definizione che restituisce le righe da due espressioni di query, indipendentemente dal fatto che le righe derivino da una o entrambe le espressioni.

INTERSECARE [TUTTI \$1 DISTINTI]  
Operazione di definizione che restituisce le righe che derivano da due espressioni di query. Le righe che non vengono restituite da entrambe le espressioni vengono scartate.

TRANNE [TUTTI \$1 DISTINTI]  
Operazione di definizione che restituisce le righe che derivano da una delle due espressioni di query. Per qualificarsi per il risultato, le righe devono esistere nella prima tabella dei risultati ma non nella seconda.   
EXCEPT ALL non rimuove i duplicati dalle righe dei risultati.  
MINUS ed EXCEPT sono sinonimi esatti. 

## Ordine di valutazione degli operatori di definizione
<a name="UNION-order-of-evaluation-for-set-operators"></a>

Gli operatori di definizione UNION ed EXCEPT sono associativi a sinistra. Se non si specificano le parentesi per influenzare l'ordine di precedenza, una combinazione di questi operatori di definizione viene valutata da sinistra a destra. Ad esempio, nella seguente query, l'operazione UNION di T1 e T2 viene valutata per prima, quindi l'operazione EXCEPT viene eseguita sul risultato di UNION: 

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

L'operatore INTERSECT ha la precedenza sugli operatori UNION ed EXCEPT quando una combinazione di operatori viene utilizzata nella stessa query. Ad esempio, la seguente query valuta l'intersezione di T2 e T3, quindi l'unione del risultato con T1: 

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

Aggiungendo le parentesi, puoi applicare un diverso ordine di valutazione. Nel seguente caso, il risultato dell'unione di T1 e T2 viene intersecato con T3 e la query produce probabilmente un risultato diverso. 

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

## Note per l'utilizzo
<a name="UNION-usage-notes"></a>
+ I nomi di colonna restituiti nel risultato di una query dell'operazione di definizione sono i nomi di colonna (o alias) delle tabelle nella prima espressione di query. Poiché questi nomi di colonne sono potenzialmente fuorvianti, in quanto i valori della colonna derivano da tabelle su entrambi i lati dell'operatore di definizione, puoi fornire alias significativi per il set di risultati.
+ Quando le query dell'operatore di definizione restituiscono risultati decimali, le colonne dei risultati corrispondenti vengono elevate per restituire la stessa precisione e scala. Ad esempio, nella seguente query, dove T1.REVENUE è una colonna DECIMAL (10,2) e T2.REVENUE è una colonna DECIMAL (8,4), il risultato decimale viene elevato a DECIMAL (12,4): 

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

  La scala è `4` perché è la scala massima delle due colonne. La precisione è `12` perché T1.REVENUE richiede 8 cifre a sinistra del punto decimale (12 - 4 = 8). Questo tipo di elevazione garantisce che tutti i valori di entrambi i lati dell'UNION si adattino al risultato. Per i valori a 64 bit, la precisione massima del risultato è 19 e la scala del risultato massimo è 18. Per i valori a 128 bit, la precisione massima del risultato è 38 e la scala del risultato massimo è 37.

  Se il tipo di dati risultante supera i limiti AWS Clean Rooms di precisione e scala, la query restituisce un errore.
+ Per le operazioni di definizione, due righe vengono considerate identiche se, per ciascuna coppia di colonne corrispondente, i due valori di dati sono *uguali* o *entrambi NULL*. Ad esempio, se le tabelle T1 e T2 contengono entrambe una colonna e una riga e tale riga è NULL in entrambe le tabelle, un'operazione INTERSECT su quelle tabelle restituisce tale riga.

# Query UNION di esempio
<a name="example_union_query"></a>

Nella seguente query UNION, le righe nella tabella SALES vengono unite alle righe nella tabella LISTING. Tre colonne compatibili sono selezionate da ciascuna tabella; in questo caso, le colonne corrispondenti hanno gli stessi nomi e tipi di dati. 

```
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
```

L'esempio seguente mostra come è possibile aggiungere un valore letterale all'output di una query UNION in modo da poter vedere quale espressione di query ha prodotto ogni riga nel set di risultati. La query identifica le righe dalla prima espressione di query come "B" (per gli acquirenti) e le righe dalla seconda espressione di query come "S" (per i venditori). 

La query identifica acquirenti e venditori per transazioni di biglietti che costano almeno \$110.000. L'unica differenza tra le due espressioni di query su entrambi i lati dell'operatore UNION è la colonna di collegamento per la tabella 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
```

L'esempio seguente utilizza un operatore UNION ALL perché le righe duplicate, se trovate, devono essere conservate nel risultato. Per una serie specifica di eventi IDs, la query restituisce 0 o più righe per ogni vendita associata a ciascun evento e 0 o 1 riga per ogni elenco di quell'evento. IDs Gli eventi sono univoci per ogni riga delle tabelle LISTING ed EVENT, ma potrebbero esserci più vendite per la stessa combinazione di evento e inserzione IDs nella tabella SALES. 

La terza colonna nel set di risultati identifica l'origine della riga. Se proviene dalla tabella SALES, è contrassegnata con "Yes" nella colonna SALESROW. SALESROW è un alias per SALES.LISTID. Se la riga proviene dalla tabella LISTING, è contrassegnata con "No" nella colonna SALESROW. 

In questo caso, il set di risultati è costituito da tre righe di vendita per l'elenco 500, evento 7787. In altre parole, sono state eseguite tre diverse transazioni per l'elenco e la combinazione di eventi. Le altre due inserzioni, 501 e 502, non hanno prodotto vendite, quindi l'unica riga generata dalla query per questi elenchi IDs proviene dalla tabella 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
```

Se esegui la stessa query senza la parola chiave ALL, il risultato conserva solo una delle transazioni di vendita. 

```
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
```

# Query UNION ALL di esempio
<a name="example_unionall_query"></a>

L'esempio seguente utilizza un operatore UNION ALL perché le righe duplicate, se trovate, devono essere conservate nel risultato. Per una serie specifica di eventi IDs, la query restituisce 0 o più righe per ogni vendita associata a ciascun evento e 0 o 1 riga per ogni elenco di quell'evento. IDs Gli eventi sono univoci per ogni riga delle tabelle LISTING ed EVENT, ma potrebbero esserci più vendite per la stessa combinazione di evento e inserzione IDs nella tabella SALES.

La terza colonna nel set di risultati identifica l'origine della riga. Se proviene dalla tabella SALES, è contrassegnata con "Yes" nella colonna SALESROW. SALESROW è un alias per SALES.LISTID. Se la riga proviene dalla tabella LISTING, è contrassegnata con "No" nella colonna SALESROW.

In questo caso, il set di risultati è costituito da tre righe di vendita per l'elenco 500, evento 7787. In altre parole, sono state eseguite tre diverse transazioni per l'elenco e la combinazione di eventi. Le altre due inserzioni, 501 e 502, non hanno prodotto vendite, quindi l'unica riga generata dalla query per questi elenchi IDs proviene dalla tabella 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
```

Se esegui la stessa query senza la parola chiave ALL, il risultato conserva solo una delle transazioni di vendita. 

```
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
```

# Query INTERSECT di esempio
<a name="example_intersect_query"></a>

Confronta il seguente esempio con il primo esempio di UNION. L'unica differenza tra i due esempi è l'operatore di definizione che viene utilizzato, ma i risultati sono molto diversi. Solo una delle righe è uguale: 

```
235494 |    23875 |    8771
```

 Questa è l'unica riga del risultato limitato di 5 righe trovata in entrambe le tabelle.

```
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
```

La seguente query trova gli eventi (per i quali sono stati venduti i biglietti) che si sono verificati nelle sedi di New York City e Los Angeles a marzo. La differenza tra le due espressioni di query è il vincolo sulla colonna 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
```

# Query EXCEPT di esempio
<a name="Example_EXCEPT_query"></a>

La tabella CATEGORY del database contiene le seguenti 11 righe: 

```
 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)
```

Supponi che una tabella CATEGORY\$1STAGE (una tabella di gestione temporanea) contenga una riga aggiuntiva: 

```
 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)
```

Restituisce la differenza tra le due tabelle. In altre parole, restituisce le righe che si trovano nella tabella CATEGORY\$1STAGE ma non nella tabella CATEGORY: 

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

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

La seguente query equivalente utilizza il sinonimo MINUS. 

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

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

Se inverti l'ordine delle espressioni SELECT, la query non restituisce alcuna riga. 

# Clausola ORDER BY
<a name="ORDER_BY_clause"></a>

La clausola ORDER BY ordina il set di risultati di una query.

**Nota**  
L'espressione ORDER BY più esterna deve contenere solo colonne presenti nell'elenco di selezione.

**Topics**
+ [Sintassi](#ORDER_BY_clause-synopsis)
+ [Parameters](#ORDER_BY_clause-parameters)
+ [Note per l'utilizzo](#ORDER_BY_usage_notes)
+ [Esempi di ORDER BY](Examples_with_ORDER_BY.md)

## Sintassi
<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>

 *espressione*   
Espressione che definisce il tipo di ordinamento del risultato della query. È costituita da una o più colonne nell'elenco di selezione. I risultati vengono restituiti in base all'ordinamento binario UTF-8. È anche possibile specificare:  
+ Numeri ordinali che rappresentano la posizione delle voci dell'elenco di selezione (o la posizione delle colonne nella tabella se non esiste alcun elenco di selezione)
+ Alias che definiscono le voci dell'elenco di selezione
Quando la clausola ORDER BY contiene più espressioni, il set di risultati viene ordinato in base alla prima espressione, quindi la seconda espressione viene applicata alle righe che presentano valori corrispondenti della prima espressione e così via.

ASC \$1 DESC   
Opzione che definisce l'ordinamento per l'espressione, come segue:   
+ ASC: crescente (ad esempio, dal più piccolo al più grande per i valori numerici e da 'A' a 'Z' per le stringhe di caratteri). Se non viene specificata alcuna opzione, i dati vengono ordinati in ordine crescente per impostazione predefinita. 
+ DESC: decrescente (ad esempio, dal più grande al più piccolo per i valori numerici e da 'Z' ad 'A' per le stringhe). 

NULLS FIRST \$1 NULLS LAST  
Opzione che specifica se i valori NULL devono essere ordinati per primi, prima dei valori non null, o per ultimi, dopo i valori non null. Per impostazione predefinita, i valori NULL vengono ordinati e classificati per ultimi in ordine ASC e ordinati e classificati per primi in ordine DESC.

LIMIT *number* \$1 ALL   <a name="order-by-clause-limit"></a>
Opzione che controlla il numero di righe ordinate restituite dalla query. Il numero LIMIT deve essere un integer positivo; il valore massimo è `2147483647`.   
LIMIT 0 non restituisce righe. Puoi utilizzare questa sintassi a scopo di test: per verificare che una query venga eseguita (senza visualizzare alcuna riga) o per restituire un elenco di colonne da una tabella. Una clausola ORDER BY è ridondante se si utilizza LIMIT 0 per restituire un elenco di colonne. L'impostazione predefinita è LIMIT ALL. 

OFFSET *start*   <a name="order-by-clause-offset"></a>
Opzione che specifica di ignorare il numero di righe prima di *start* prima di iniziare a restituire righe. Il numero OFFSET deve essere un integer intero positivo; il valore massimo è `2147483647`. Se utilizzato con l'opzione LIMIT, le righe OFFSET vengono ignorate prima di iniziare a contare le righe LIMIT restituite. Se non si utilizza l'opzione LIMIT, il numero di righe nel set dei risultati viene ridotto del numero di righe che vengono ignorate. Le righe ignorate da una clausola OFFSET devono ancora essere analizzate, quindi potrebbe essere inefficiente utilizzare un valore OFFSET di grandi dimensioni.

## Note per l'utilizzo
<a name="ORDER_BY_usage_notes"></a>

 Nota il seguente comportamento previsto con le clausole ORDER BY: 
+ I valori NULL sono considerati "superiori" rispetto a tutti gli altri valori. Con l'ordine di ordinamento crescente predefinito, i valori NULL vengono ordinati alla fine. Per modificare questo comportamento, utilizza l'opzione NULLS FIRST.
+ Quando una query non contiene una clausola ORDER BY, il sistema restituisce serie di risultati senza ordine prevedibile delle righe. La stessa query eseguita due volte potrebbe restituire il set di risultati in un ordine diverso. 
+ Le opzioni LIMIT e OFFSET possono essere utilizzate senza una clausola ORDER BY; tuttavia, per restituire un insieme coerente di righe, utilizza queste opzioni insieme a ORDER BY. 
+ In qualsiasi sistema parallelo come AWS Clean Rooms, quando ORDER BY non produce un ordinamento univoco, l'ordine delle righe non è deterministico. Cioè, se l'espressione ORDER BY produce valori duplicati, l'ordine di restituzione di tali righe potrebbe variare da un sistema all'altro o da un'esecuzione all'altra. AWS Clean Rooms 
+ AWS Clean Rooms non supporta stringhe letterali nelle clausole ORDER BY.

# Esempi di ORDER BY
<a name="Examples_with_ORDER_BY"></a>

Restituisce tutte le 11 righe dalla tabella CATEGORY, ordinate in base alla seconda colonna CATGROUP. Per i risultati con lo stesso valore CATGROUP, ordina i valori della colonna CATDESC in base alla lunghezza della stringa di caratteri. Quindi ordina per colonne CATID e CATNAME. 

```
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)
```

Restituisce le colonne selezionate dalla tabella SALES, ordinate in base ai valori QTYSOLD più alti. Limita il risultato alle prime 10 righe: 

```
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
```

Restituisce un elenco di colonne e nessuna riga usando la sintassi LIMIT 0: 

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

# Esempi di sottoquery
<a name="Subquery_examples"></a>

Gli esempi seguenti mostrano diversi modi in cui le sottoquery si adattano alle query SELECT. Per un altro esempio dell'uso delle sottoquery, consultare [Esempio](join-clause.md#Join_examples). 

## Sottoquery dell'elenco SELECT
<a name="Subquery_examples-select-list-subquery"></a>

L'esempio seguente contiene una sottoquery nell'elenco SELECT. Questa sottoquery è *scalar*: restituisce solo una colonna e un valore, che viene ripetuto nel risultato per ogni riga restituita dalla query esterna. La query confronta il valore Q1SALES che la sottoquery calcola con i valori di vendita per due altri trimestri (2 e 3) nel 2008, come definito dalla query esterna. 

```
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)
```

## Sottoquery della clausola WHERE
<a name="Subquery_examples-where-clause-subquery"></a>

L'esempio seguente contiene una sottoquery di tabella nella clausola WHERE. Questa sottoquery produce più righe. In questo caso, le righe contengono solo una colonna, ma le sottoquery di tabella possono contenere più colonne e righe, proprio come qualsiasi altra tabella. 

La query trova i primi 10 venditori in termini di numero di biglietti venduti. L'elenco dei primi 10 è limitato dalla sottoquery che rimuove gli utenti che vivono in città dove ci sono le sedi dei biglietti. Questa query può essere scritta in diversi modi; ad esempio, la sottoquery potrebbe essere riscritta come un join all'interno della query principale. 

```
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)
```

## Sottoquery della clausola WITH
<a name="Subquery_examples-with-clause-subqueries"></a>

Per informazioni, consulta [Clausola WITH](WITH_clause.md). 

# Sottoquery correlate
<a name="correlated_subqueries"></a>

L'esempio seguente contiene una *sottoquery correlata* nella clausola WHERE; questo tipo di sottoquery contiene una o più correlazioni tra le sue colonne e le colonne prodotte dalla query esterna. In questo caso, la correlazione è `where s.listid=l.listid`. Per ogni riga prodotta dalla query esterna, la sottoquery viene eseguita per qualificare o squalificare la riga. 

```
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)
```

## Modelli di sottoquery correlate non supportate
<a name="correlated_subqueries-correlated-subquery-patterns-that-are-not-supported"></a>

Il pianificatore di query utilizza un metodo di riscrittura delle query denominato decorrelazione delle sottoquery per ottimizzare diversi modelli di sottoquery correlate per l'esecuzione in un ambiente MPP. Alcuni tipi di sottoquery correlate seguono schemi che non AWS Clean Rooms possono essere decorrelate e che non supportano. Le query che contengono i seguenti riferimenti di correlazione restituiscono errori: 
+  Riferimenti di correlazione che ignorano un blocco di query, noti anche come "riferimenti di correlazione ignorati". Ad esempio, nella seguente query, il blocco contenente il riferimento di correlazione e il blocco ignorato sono collegati da un predicato NOT EXISTS: 

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

  Il blocco ignorato in questo caso è la sottoquery rispetto alla tabella LISTING. Il riferimento di correlazione correla le tabelle EVENT e SALES. 
+  Riferimenti di correlazione di una sottoquery che fa parte di una clausola ON in una query esterna: 

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

  La clausola ON contiene un riferimento di correlazione da SALES nella sottoquery a EVENT nella query esterna. 
+ Riferimenti di correlazione sensibili a valori nulli a una tabella di sistema. AWS Clean Rooms Esempio: 

  ```
  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);
  ```
+ Riferimenti di correlazione da una sottoquery contenente una funzione finestra. 

  ```
  select listid, qtysold
  from sales s
  where qtysold not in
  (select sum(numtickets) over() from listing l where s.listid=l.listid);
  ```
+ Riferimenti in una colonna GROUP BY ai risultati di una sottoquery correlata. Ad esempio: 

  ```
  select listing.listid,
  (select count (sales.listid) from sales where sales.listid=listing.listid) as list
  from listing
  group by list, listing.listid;
  ```
+ Riferimenti di correlazione da una sottoquery con una funzione di aggregazione e una clausola GROUP BY, connessi alla query esterna da un predicato IN. Questa restrizione non si applica alle funzioni di aggregazione MIN e MAX. Esempio: 

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