

 Amazon Redshift ne prendra plus en charge la création de nouveaux Python à UDFs partir du patch 198. UDFs Le Python existant continuera de fonctionner jusqu'au 30 juin 2026. Pour plus d’informations, consultez le [ billet de blog ](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/). 

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Didacticiel : Faire une requête de données imbriquées avec Amazon Redshift Spectrum
<a name="tutorial-query-nested-data"></a>

Ce didacticiel explique comment interroger des données imbriquées avec Redshift Spectrum. Les données imbriquées sont des données qui contiennent des champs imbriqués. Les champs imbriqués sont des champs assemblés en une seule entité, tels que des tableaux, des structures ou des objets. 

**Topics**
+ [Présentation de](#tutorial-nested-data-overview)
+ [Étape 1 : Création d’un tableau externe contenant des données imbriquées](#tutorial-nested-data-create-table)
+ [Étape 2 : Faire une requête de vos données imbriquées dans Amazon S3 avec des extensions SQL](#tutorial-query-nested-data-sqlextensions)
+ [Cas d’utilisation de données imbriquées](nested-data-use-cases.md)
+ [Limitations des données imbriquées (version préliminaire)](nested-data-restrictions.md)
+ [Sérialisation de JSON imbriqué complexe](serializing-complex-JSON.md)

## Présentation de
<a name="tutorial-nested-data-overview"></a>

Amazon Redshift Spectrum prend en charge la requête de données imbriquées dans Parquet, ORC, JSON et les formats de fichier Ion. Redshift Spectrum accède aux données à l’aide de tableaux externes. Vous pouvez créer des tableaux externes qui utilisent les types de données complexes `struct`, `array`, et `map`.

Par exemple, supposons que votre fichier de données contienne les données suivantes dans Amazon S3 dans un fichier nommé `customers`. Bien qu’il n’y ait aucun élément racine, chaque objet JSON de cet exemple de données représente une ligne d’une table. 

```
{"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}]
}
```

Vous pouvez utiliser Amazon Redshift Spectrum pour soumettre une requête sur les données imbriquées dans des fichiers. Le didacticiel suivant vous montre comment effectuer cette opération avec les données Apache Parquet.

### Conditions préalables
<a name="tutorial-nested-data-prereq"></a>

Si vous n’utilisez pas encore Redshift Spectrum, suivez les étapes détaillées dans [Mise en route avec Amazon Redshift Spectrum](c-getting-started-using-spectrum.md) avant de poursuivre.

Pour créer un schéma externe, remplacez l’ARN de rôle IAM dans la commande suivante par l’ARN de rôle que vous avez créé dans [Créer un rôle IAM](c-getting-started-using-spectrum.md#c-getting-started-using-spectrum-create-role). Ensuite, exécutez la commande dans votre 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;
```

## Étape 1 : Création d’un tableau externe contenant des données imbriquées
<a name="tutorial-nested-data-create-table"></a>

Vous pouvez afficher les [données source](https://s3.amazonaws.com/redshift-downloads/tickit/spectrum/customers/customer_file1) en les téléchargeant depuis Amazon S3. 

Exécutez la commande suivante pour créer un tableau externe pour ce didacticiel. 

```
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/';
```

Dans l’exemple précédent, le tableau externe `spectrum.customers` utilise les types de données `struct` et `array` pour définir les colonnes dotées de données imbriquées. Amazon Redshift Spectrum prend en charge la requête de données imbriquées dans Parquet, ORC, JSON et les formats de fichier Ion. Le paramètre `STORED AS` est `PARQUET` pour les fichiers Apache Parquet. Le paramètre `LOCATION` doit se référer au dossier Amazon S3 contenant les données ou fichiers imbriqués. Pour de plus amples informations, veuillez consulter [CREATE EXTERNAL TABLE](r_CREATE_EXTERNAL_TABLE.md).

Vous pouvez imbriquer les types `array` et `struct` à n’importe quel niveau. Vous pouvez par exemple définir une colonne nommée `toparray`, comme l’illustre l’exemple suivant.

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

Vous pouvez également imbriquer les types `struct` comme l’illustre la colonne `x` dans l’exemple suivant.

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

## Étape 2 : Faire une requête de vos données imbriquées dans Amazon S3 avec des extensions SQL
<a name="tutorial-query-nested-data-sqlextensions"></a>

Redshift Spectrum prend en charge les requêtes de types complexes `array`, `map` et `struct` via des extensions à la syntaxe SQL Amazon Redshift. 

### Extension 1 : Accès aux colonnes de structs
<a name="nested-data-sqlextension1"></a>

Vous pouvez extraire des données à partir des colonnes `struct` à l’aide d’une notation par points qui connecte les noms de champs en chemins. Par exemple, la requête suivante retourne les noms et prénoms de clients. Le prénom est obtenu via le long chemin `c.name.given`. Le nom de famille est obtenu via le long chemin `c.name.family`. 

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

La requête précédente renvoie les données suivantes.

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

Un `struct` peut être une colonne d’un autre `struct`, qui peut être une colonne d’un autre `struct` et ce à tout niveau. Les chemins qui accèdent aux colonnes dans des `struct` aussi profondément imbriqués peuvent être très longs. Par exemple, regardez la définition pour la colonne `x` dans l’illustration suivante.

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

Vous pouvez accéder aux données dans `e` en tant que `x.b.d.e`.

### Extension 2 : Surplomber les pans d’une clause FROM
<a name="nested-data-sqlextension2"></a>

Vous pouvez extraire des données de colonnes `array` (et, par extension, des colonnes `map`) en précisant les colonnes `array` dans une clause `FROM` à la place des noms de tableaux. L’extension s’applique à la clause `FROM` de la requête principale, ainsi qu’aux clauses `FROM` des sous-requêtes.

Vous pouvez référencer les éléments `array` d’après leur position, comme `c.orders[0]` (version préliminaire).

En combinant le surplombage de `arrays` avec des raccords, vous pouvez réaliser différentes sortes de désimbrication, comme les cas d’utilisation suivants l’expliquent. 

#### Désimbrication à l’aide de raccords internes
<a name="unnest-inner-joins"></a>

La requête suivante sélectionne les dates d'expédition IDs des clients et des commandes pour les clients qui ont des commandes. L’extension SQL dans la clause FROM `c.orders o` dépend de l’alias `c`.

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

Pour chaque `c` de client disposant de commandes, la clause `FROM` renvoie une ligne pour chaque commande `o` du client `c`. Cette ligne combine la ligne du client `c` et la ligne de commande `o`. Ensuite, la clause `SELECT` garde uniquement le `c.id` et le `o.shipdate`. Le résultat est le suivant.

```
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` fournit un accès aux champs du client et l’alias `o` fournit un accès aux champs de commande. 

La sémantique est similaire au SQL standard. Vous pouvez envisager la clause `FROM` comme exécutant la boucle imbriquée suivante qui est suivie par la sélection de champs pour la sortie par `SELECT`. 

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

Ainsi, si un client ne dispose pas de commande, le client n’apparaît pas dans le résultat.

Vous pouvez également envisager ceci comme une clause `FROM` qui exécute un `JOIN` avec le tableau `customers` et le pan `orders`. Dans les faits, vous pouvez également rédiger la requête comme l’illustre l’exemple suivant.

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

**Note**  
Si un schéma nommé `c` existe avec un tableau nommé `orders`, alors `c.orders` se réfère au tableau `orders`, et non à la colonne de pan `customers`.

#### Désimbrication à l’aide de raccords gauches
<a name="unnest-left-joins"></a>

La requête suivante sort tous les noms des clients et leurs commandes. Si un client n’a pas encore placé de commande, son nom sera tout de même renvoyé. Cependant, dans ce cas, les colonnes de commande sont NULLES, comme l’illustre l’exemple suivant pour 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 requête précédente renvoie les données suivantes.

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

### Extension 3 : Obtenir directement à un pan de scalaires en utilisant un alias
<a name="nested-data-sqlextension3"></a>

Lorsqu’un alias `p` dans une clause `FROM` surplombe tout un tableau de scalaires, la requête se réfère aux valeurs de `p` en tant que `p`. Par exemple, la requête suivante produit des paires de noms de clients et de numéros de téléphone.

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

La requête précédente renvoie les données suivantes.

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

### Extension 4 : Accès aux éléments de cartes
<a name="nested-data-sqlextension4"></a>

Redshift Spectrum traite le type de donnée `map` comme un type de `array` contenant des types `struct` avec une colonne `key` et une colonne `value`. La `key` doit être `scalar`; la valeur peut être de n’importe quel type de donnée. 

Par exemple, le code suivant crée un tableau externe avec une `map` pour stocker les numéros de téléphone.

```
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/';
```

Parce qu’un type de `map` se comporte comme un type de `array` avec des colonnes `key` et `value`, vous pouvez penser aux schémas précédents comme s’ils étaient les suivants.

```
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 requête suivante renvoie les noms de clients avec un numéro de téléphone mobile et renvoie le numéro pour chaque nom. La requête de carte est traitée comme l’équivalent d’une requête de `array` imbriquée de types `struct`. La requête suivante ne renvoie des données que si vous avez créé le tableau externe précédemment évoqué. 

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

**Note**  
La `key` pour une `map` est une `string` pour les types de fichiers Ion et JSON.