

 Amazon Redshift non supporterà più la creazione di nuovi Python UDFs a partire dalla Patch 198. Python esistente UDFs continuerà a funzionare fino al 30 giugno 2026. Per ulteriori informazioni, consulta il [post del blog](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/). 

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à.

# Tutorial: Esecuzione di query su dati nidificati con Amazon Redshift Spectrum
<a name="tutorial-query-nested-data"></a>

In questo tutorial viene dimostrato come eseguire query sui dati annidati con Redshift Spectrum. I dati annidati sono dati che contengono campi annidati. I campi annidati sono campi di cui è stato effettuato il join come un’unica entità, quali array, strutture oppure oggetti. 

**Topics**
+ [Panoramica di](#tutorial-nested-data-overview)
+ [Fase 1: creazione di una tabella esterna contenente dati nidificati](#tutorial-nested-data-create-table)
+ [Fase 2: Esecuzione di query sui dati nidificati in Amazon S3 con estensioni SQL](#tutorial-query-nested-data-sqlextensions)
+ [Casi d'uso dei dati nidificati](nested-data-use-cases.md)
+ [Limitazioni relative ai dati annidati (anteprima)](nested-data-restrictions.md)
+ [Serializzazione di JSON nidificato complesso](serializing-complex-JSON.md)

## Panoramica di
<a name="tutorial-nested-data-overview"></a>

Amazon Redshift Spectrum supporta l'esecuzione di query di dati nidificati nei formati di file Parquet, ORC, JSON e Ion. Redshift Spectrum accede ai dati mediante tabelle esterne. Puoi creare tabelle esterne che utilizzano i tipi di dati complessi `struct`, `array` e `map`.

Ad esempio, si supponga che il file di dati contenga i seguenti dati in Amazon S3 all'interno di una cartella denominata `customers`. Anche se non è presente un singolo elemento root, ciascun oggetto JSON in questi dati di esempio rappresenta una riga in una tabella. 

```
{"id": 1,
 "name": {"given": "John", "family": "Smith"},
 "phones": ["123-457789"],
 "orders": [{"shipdate": "2018-03-01T11:59:59.000Z", "price": 100.50},
            {"shipdate": "2018-03-01T09:10:00.000Z", "price": 99.12}]
}
{"id": 2,
 "name": {"given": "Jenny", "family": "Doe"},
 "phones": ["858-8675309", "415-9876543"],
 "orders": []
}
{"id": 3,
 "name": {"given": "Andy", "family": "Jones"},
 "phones": [],
 "orders": [{"shipdate": "2018-03-02T08:02:15.000Z", "price": 13.50}]
}
```

Puoi utilizzare Amazon Redshift Spectrum per eseguire query sui dati nidificati nei file. Il seguente tutorial illustra la procedura da seguire con i dati Apache Parquet.

### Prerequisiti
<a name="tutorial-nested-data-prereq"></a>

Se ancora non utilizzi Redshift Spectrum, segui la procedura in [Nozioni di base su Amazon Redshift Spectrum](c-getting-started-using-spectrum.md) prima di continuare.

Per creare uno schema esterno, sostituire l'ARN del ruolo IAM nel comando seguente con l'ARN del ruolo creato in [Creazione di un ruolo IAM](c-getting-started-using-spectrum.md#c-getting-started-using-spectrum-create-role). Quindi eseguire il comando nel proprio client SQL.

```
create external schema spectrum 
from data catalog 
database 'myspectrum_db' 
iam_role 'arn:aws:iam::123456789012:role/myspectrum_role'
create external database if not exists;
```

## Fase 1: creazione di una tabella esterna contenente dati nidificati
<a name="tutorial-nested-data-create-table"></a>

È possibile visualizzare i [dati di origine](https://s3.amazonaws.com/redshift-downloads/tickit/spectrum/customers/customer_file1) scaricandoli da Amazon S3. 

Per creare la tabella esterna per questo tutorial, utilizza il comando seguente. 

```
CREATE EXTERNAL TABLE spectrum.customers (
  id     int,
  name   struct<given:varchar(20), family:varchar(20)>,
  phones array<varchar(20)>,
  orders array<struct<shipdate:timestamp, price:double precision>>
)
STORED AS PARQUET
LOCATION 's3://redshift-downloads/tickit/spectrum/customers/';
```

Nell'esempio precedente, la tabella esterna `spectrum.customers` utilizza i tipi di dati `struct` e `array` per definire colonne con dati nidificati. Amazon Redshift Spectrum supporta l'esecuzione di query di dati nidificati nei formati di file Parquet, ORC, JSON e Ion. Il parametro `STORED AS` è `PARQUET` per i file Apache Parquet. Il parametro `LOCATION` deve fare riferimento alla cartella Amazon S3 che contiene i file o i dati nidificati. Per ulteriori informazioni, consulta [CREATE EXTERNAL TABLE](r_CREATE_EXTERNAL_TABLE.md).

Puoi nidificare tipi `array` e `struct` a qualsiasi livello. Ad esempio, puoi definire una colonna denominata `toparray` come mostrato nell'esempio seguente.

```
toparray array<struct<nestedarray:
         array<struct<morenestedarray: 
         array<string>>>>>
```

Puoi inoltre nidificare tipi `struct` come mostrato per la colonna `x` nell'esempio seguente.

```
x struct<a: string,
         b: struct<c: integer,
                   d: struct<e: string>
                  >
        >
```

## Fase 2: Esecuzione di query sui dati nidificati in Amazon S3 con estensioni SQL
<a name="tutorial-query-nested-data-sqlextensions"></a>

Redshift Spectrum supporta l'esecuzione di query su tipi complessi `array`, `map` e `struct` mediante estensioni alla sintassi SQL di Amazon Redshift. 

### Estensione 1: accesso a colonne di struct
<a name="nested-data-sqlextension1"></a>

Puoi estrarre dati da colonne `struct` utilizzando una notazione punto che concatena i nomi dei campi in percorsi. Ad esempio, la query seguente restituisce il nome e il cognome dei clienti. L'accesso al nome viene eseguito dal percorso lungo `c.name.given`. L'accesso al cognome viene eseguito dal percorso lungo `c.name.family`. 

```
SELECT c.id, c.name.given, c.name.family
FROM   spectrum.customers c;
```

La query precedente restituisce i seguenti dati.

```
id | given | family
---|-------|-------
1  | John  | Smith
2  | Jenny | Doe
3  | Andy  | Jones
(3 rows)
```

Uno `struct` può essere una colonna di un altro `struct`, che a sua volta può essere una colonna di un altro `struct`, a qualsiasi livello. I percorsi di accesso alle colonne in `struct` nidificati in modo così profondo possono essere lunghi. Ad esempio, consultare la definizione relativa alla colonna `x` nell'esempio seguente.

```
x struct<a: string,
         b: struct<c: integer, 
                      d: struct<e: string>
                  >
        >
```

Puoi accedere ai dati in `e` come `x.b.d.e`.

### Estensione 2: matrici estese a una clausola FROM
<a name="nested-data-sqlextension2"></a>

Puoi estrarre dati da colonne `array` (e, per estensione, da colonne `map`) specificando le colonne `array` in una clausola `FROM` al posto dei nomi delle tabelle. L'estensione si applica alla clausola `FROM` della query principale e, inoltre, alle clausole `FROM` delle query secondarie.

Puoi fare riferimento a elementi `array` in base alla posizione, ad esempio `c.orders[0]` (anteprima).

Combinando `arrays` estese e join, puoi annullare annidamenti in vari modi, come illustrato nei seguenti casi d'uso. 

#### Annullamento di annidamenti mediante inner join
<a name="unnest-inner-joins"></a>

La seguente query seleziona le date di spedizione del cliente IDs e dell'ordine per i clienti che hanno ordini. L'estensione SQL nella clausola FROM `c.orders o` dipende dall'alias `c`.

```
SELECT c.id, o.shipdate
FROM   spectrum.customers c, c.orders o
```

Per ciascun cliente `c` associato a degli ordini, la clausola `FROM` restituisce una riga per ogni ordine `o` del cliente `c`. La riga in questione combina la riga del cliente `c` e quella dell'ordine `o`. In seguito, la clausola `SELECT` mantiene solo `c.id` e `o.shipdate`. Il risultato è il seguente.

```
id|      shipdate
--|----------------------
1 |2018-03-01  11:59:59
1 |2018-03-01  09:10:00
3 |2018-03-02  08:02:15
(3 rows)
```

L'alias `c` fornisce l'accesso ai campi dei clienti, mentre l'alias `o` consente l'accesso ai campi degli ordini. 

La semantica è simile a quella di SQL standard. È possibile pensare a un processo in cui la clausola `FROM` esegue il loop nidificato mostrato sotto, mentre `SELECT` sceglie i campi da restituire. 

```
for each customer c in spectrum.customers
  for each order o in c.orders
     output c.id and o.shipdate
```

Pertanto, se un cliente non è associato ad alcun ordine, non verrà mostrato tra i risultati.

Puoi pensare anche a un processo in cui la clausola `FROM` esegue un `JOIN` con la tabella `customers` e la matrice `orders`. In effetti, puoi anche scrivere la query, come mostrato nell'esempio seguente.

```
SELECT c.id, o.shipdate
FROM   spectrum.customers c INNER JOIN c.orders o ON true
```

**Nota**  
Se è presente uno schema denominato `c` con una tabella chiamata `orders`, allora `c.orders` fa riferimento alla tabella `orders` e non alla colonna della matrice di `customers`.

#### Annullamento di annidamenti mediante left join
<a name="unnest-left-joins"></a>

La query seguente restituisce tutti i nomi dei clienti e i loro ordini. Se un cliente non ha effettuato alcun ordine, il suo nome viene comunque restituito. Tuttavia, in questo caso, l'ordine presenta colonne NULL, come mostrato nell'esempio seguente per Jenny Doe.

```
SELECT c.id, c.name.given, c.name.family, o.shipdate, o.price
FROM   spectrum.customers c LEFT JOIN c.orders o ON true
```

La query precedente restituisce i seguenti dati.

```
id  |  given  | family  |    shipdate          | price
----|---------|---------|----------------------|--------
 1  |  John   | Smith   | 2018-03-01  11:59:59 | 100.5
 1  |  John   | Smith   | 2018-03-01  09:10:00 |  99.12
 2  |  Jenny  | Doe     |                      |
 3  |  Andy   | Jones   | 2018-03-02  08:02:15 |  13.5
 (4 rows)
```

### Estensione 3: accesso diretto a una matrice di scalari tramite un alias
<a name="nested-data-sqlextension3"></a>

Quando un alias `p` in una clausola `FROM` si estende a una matrice di scalari, la query fa riferimento ai valori di `p` come `p`. Ad esempio, la query seguente genera coppie di nomi e numeri di telefono dei clienti.

```
SELECT c.name.given, c.name.family, p AS phone
FROM   spectrum.customers c LEFT JOIN c.phones p ON true
```

La query precedente restituisce i seguenti dati.

```
given  |  family  |  phone
-------|----------|-----------
John   | Smith    | 123-4577891
Jenny  | Doe      | 858-8675309
Jenny  | Doe      | 415-9876543
Andy   | Jones    | 
(4 rows)
```

### Estensione 4: accesso agli elementi del tipo di dati map
<a name="nested-data-sqlextension4"></a>

Redshift Spectrum tratta `map` come un tipo di dati `array` che contiene tipi `struct` con una colonna `key` e una colonna `value`. `key` deve essere uno `scalar`; il valore può essere qualunque tipo di dati. 

Ad esempio, il codice seguente crea una tabella esterna con un tipo `map` per l'archiviazione dei numeri di telefono.

```
CREATE EXTERNAL TABLE spectrum.customers2 (
  id     int,
  name   struct<given:varchar(20), family:varchar(20)>,
  phones map<varchar(20), varchar(20)>,
  orders array<struct<shipdate:timestamp, price:double precision>>
)
STORED AS PARQUET
LOCATION 's3://redshift-downloads/tickit/spectrum/customers/';
```

Dal momento che un tipo `map` si comporta come un tipo `array` con colonne `key` e `value`, puoi pensare agli schemi precedenti come a quelli riportati di seguito.

```
CREATE EXTERNAL TABLE spectrum.customers3 (
  id     int,
  name   struct<given:varchar(20), family:varchar(20)>,
  phones array<struct<key:varchar(20), value:varchar(20)>>,
  orders array<struct<shipdate:timestamp, price:double precision>>
)
STORED AS PARQUET
LOCATION 's3://redshift-downloads/tickit/spectrum/customers/';
```

La query seguente restituisce i nomi dei clienti con un numero di cellulare e il numero per ciascun nome. La query sul tipo map viene considerata equivalente a una query su un `array` nidificato di tipi `struct`. La query seguente restituisce dati solo se hai creato la tabella esterna come descritto in precedenza. 

```
SELECT c.name.given, c.name.family, p.value 
FROM   spectrum.customers c, c.phones p 
WHERE  p.key = 'mobile';
```

**Nota**  
La `key` per un tipo `map` è una `string` per i tipi di file Ion e JSON.