En GoogleSQL pour BigQuery, un tableau est une liste ordonnée composée de zéro ou plusieurs valeurs du même type de données. Vous pouvez construire des tableaux de types de données simples, tels que INT64
, et de types de données complexes, tels que STRUCT
. La seule exception en date est le type de données ARRAY
: les tableaux de tableaux ne sont pas acceptés. Pour en savoir plus sur le type de données ARRAY
, y compris sur la gestion NULL
, consultez la section Type de tableau.
GoogleSQL permet de construire des littéraux de tableau, de créer des tableaux à partir de sous-requêtes à l'aide de la fonction ARRAY
et d'agréger des valeurs dans un tableau à l'aide de la fonction ARRAY_AGG
.
Vous pouvez combiner des tableaux à l'aide de fonctions telles que ARRAY_CONCAT()
et convertir des tableaux en chaînes à l'aide de la fonction ARRAY_TO_STRING()
.
Accéder aux éléments de tableau
Prenons l'exemple de la table émulée suivante, nommée Sequences
. Cette table contient la colonne some_numbers
comportant des données de type ARRAY
.
WITH
Sequences AS (
SELECT [0, 1, 1, 2, 3, 5] AS some_numbers UNION ALL
SELECT [2, 4, 8, 16, 32] UNION ALL
SELECT [5, 10]
)
SELECT * FROM Sequences
/*---------------------*
| some_numbers |
+---------------------+
| [0, 1, 1, 2, 3, 5] |
| [2, 4, 8, 16, 32] |
| [5, 10] |
*---------------------*/
Pour accéder aux éléments de tableau dans la colonne some_numbers
, spécifiez le type d'indexation que vous souhaitez utiliser : soit index
ou OFFSET(index)
pour les index basés sur zéro, soit ORDINAL(index)
pour les index basés sur un.
Par exemple :
SELECT
some_numbers,
some_numbers[0] AS index_0,
some_numbers[OFFSET(1)] AS offset_1,
some_numbers[ORDINAL(1)] AS ordinal_1
FROM Sequences
/*--------------------+---------+----------+-----------*
| some_numbers | index_0 | offset_1 | ordinal_1 |
+--------------------+---------+----------+-----------+
| [0, 1, 1, 2, 3, 5] | 0 | 1 | 0 |
| [2, 4, 8, 16, 32] | 2 | 4 | 2 |
| [5, 10] | 5 | 10 | 5 |
*--------------------+---------+----------+-----------*/
Connaître les longueurs
La fonction ARRAY_LENGTH
renvoie la longueur d'un tableau.
WITH Sequences AS
(SELECT [0, 1, 1, 2, 3, 5] AS some_numbers
UNION ALL SELECT [2, 4, 8, 16, 32] AS some_numbers
UNION ALL SELECT [5, 10] AS some_numbers)
SELECT some_numbers,
ARRAY_LENGTH(some_numbers) AS len
FROM Sequences;
/*--------------------+--------*
| some_numbers | len |
+--------------------+--------+
| [0, 1, 1, 2, 3, 5] | 6 |
| [2, 4, 8, 16, 32] | 5 |
| [5, 10] | 2 |
*--------------------+--------*/
Convertir les éléments d'un tableau en lignes d'une table
Pour convertir un objet ARRAY
en un ensemble de lignes (processus appelé "aplatissement"), utilisez l'opérateur UNNEST
. UNNEST
prend un objet ARRAY
et renvoie une table avec une seule ligne pour chaque élément de l'ARRAY
.
Comme UNNEST
détruit l'ordre des éléments de l'objet ARRAY
, vous souhaiterez peut-être rétablir l'ordre dans la table. Pour ce faire, utilisez la clause optionnelle WITH OFFSET
pour afficher une colonne supplémentaire contenant le décalage de chaque élément de tableau, puis utilisez la clause ORDER BY
pour classer les lignes en fonction de leur décalage.
Exemple
SELECT *
FROM UNNEST(['foo', 'bar', 'baz', 'qux', 'corge', 'garply', 'waldo', 'fred'])
AS element
WITH OFFSET AS offset
ORDER BY offset;
/*----------+--------*
| element | offset |
+----------+--------+
| foo | 0 |
| bar | 1 |
| baz | 2 |
| qux | 3 |
| corge | 4 |
| garply | 5 |
| waldo | 6 |
| fred | 7 |
*----------+--------*/
Pour aplatir une colonne entière d'objets ARRAY
tout en conservant les valeurs des autres colonnes de chaque ligne, utilisez une jointure croisée corrélée pour joindre la table contenant la colonne d'objets ARRAY
au résultat de l'opérateur UNNEST
appliqué à cette colonne d'objets ARRAY
.
Avec une jointure corrélée, l'opérateur UNNEST
référence la colonne typée ARRAY
de chaque ligne de la table source, qui apparaît précédemment dans la clause FROM
. Pour chaque ligne N
de la table source, l'opérateur UNNEST
aplatit l'objet ARRAY
à partir de la ligne N
en un ensemble de lignes contenant les éléments de l'objet ARRAY
, puis la jointure croisée joint ce nouvel ensemble de lignes à la ligne unique N
de la table source.
Exemples
L'exemple suivant utilise l'opérateur UNNEST
pour renvoyer une ligne pour chaque élément de la colonne de tableaux. Avec la commande CROSS JOIN
, la colonne id
contient les valeurs id
de la ligne dans la table Sequences
comportant chaque nombre.
WITH Sequences AS
(SELECT 1 AS id, [0, 1, 1, 2, 3, 5] AS some_numbers
UNION ALL SELECT 2 AS id, [2, 4, 8, 16, 32] AS some_numbers
UNION ALL SELECT 3 AS id, [5, 10] AS some_numbers)
SELECT id, flattened_numbers
FROM Sequences
CROSS JOIN UNNEST(Sequences.some_numbers) AS flattened_numbers;
/*------+-------------------*
| id | flattened_numbers |
+------+-------------------+
| 1 | 0 |
| 1 | 1 |
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 1 | 5 |
| 2 | 2 |
| 2 | 4 |
| 2 | 8 |
| 2 | 16 |
| 2 | 32 |
| 3 | 5 |
| 3 | 10 |
*------+-------------------*/
Notez que pour les jointures croisées corrélées, l'opérateur UNNEST
est facultatif et le champ CROSS JOIN
peut être exprimé en tant que jointure croisée séparée par des virgules. En utilisant cette notation abrégée, l'exemple précédent est consolidé comme suit :
WITH Sequences AS
(SELECT 1 AS id, [0, 1, 1, 2, 3, 5] AS some_numbers
UNION ALL SELECT 2 AS id, [2, 4, 8, 16, 32] AS some_numbers
UNION ALL SELECT 3 AS id, [5, 10] AS some_numbers)
SELECT id, flattened_numbers
FROM Sequences, Sequences.some_numbers AS flattened_numbers;
/*------+-------------------*
| id | flattened_numbers |
+------+-------------------+
| 1 | 0 |
| 1 | 1 |
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 1 | 5 |
| 2 | 2 |
| 2 | 4 |
| 2 | 8 |
| 2 | 16 |
| 2 | 32 |
| 3 | 5 |
| 3 | 10 |
*------+-------------------*/
Lancer des requêtes sur des tableaux imbriqués
Si une table contient un objet ARRAY
de données STRUCT
, vous pouvez aplatir l'objet ARRAY
pour effectuer des requêtes sur les champs de données STRUCT
.
Vous pouvez également aplatir les champs ARRAY
de valeurs STRUCT
.
Rechercher des éléments STRUCT
dans un tableau
L'exemple suivant utilise UNNEST
en combinaison avec CROSS JOIN
pour aplatir un ARRAY
d'éléments STRUCT
.
WITH Races AS (
SELECT "800M" AS race,
[STRUCT("Rudisha" AS name, [23.4, 26.3, 26.4, 26.1] AS laps),
STRUCT("Makhloufi" AS name, [24.5, 25.4, 26.6, 26.1] AS laps),
STRUCT("Murphy" AS name, [23.9, 26.0, 27.0, 26.0] AS laps),
STRUCT("Bosse" AS name, [23.6, 26.2, 26.5, 27.1] AS laps),
STRUCT("Rotich" AS name, [24.7, 25.6, 26.9, 26.4] AS laps),
STRUCT("Lewandowski" AS name, [25.0, 25.7, 26.3, 27.2] AS laps),
STRUCT("Kipketer" AS name, [23.2, 26.1, 27.3, 29.4] AS laps),
STRUCT("Berian" AS name, [23.7, 26.1, 27.0, 29.3] AS laps)]
AS participants)
SELECT
race,
participant
FROM Races AS r
CROSS JOIN UNNEST(r.participants) AS participant;
/*------+---------------------------------------*
| race | participant |
+------+---------------------------------------+
| 800M | {Rudisha, [23.4, 26.3, 26.4, 26.1]} |
| 800M | {Makhloufi, [24.5, 25.4, 26.6, 26.1]} |
| 800M | {Murphy, [23.9, 26, 27, 26]} |
| 800M | {Bosse, [23.6, 26.2, 26.5, 27.1]} |
| 800M | {Rotich, [24.7, 25.6, 26.9, 26.4]} |
| 800M | {Lewandowski, [25, 25.7, 26.3, 27.2]} |
| 800M | {Kipketer, [23.2, 26.1, 27.3, 29.4]} |
| 800M | {Berian, [23.7, 26.1, 27, 29.3]} |
*------+---------------------------------------*/
Vous pouvez trouver des informations spécifiques à partir de champs répétés. Par exemple, la requête suivante renvoie le coureur le plus rapide lors d'une course sur 800 m.
Exemple
WITH Races AS (
SELECT "800M" AS race,
[STRUCT("Rudisha" AS name, [23.4, 26.3, 26.4, 26.1] AS laps),
STRUCT("Makhloufi" AS name, [24.5, 25.4, 26.6, 26.1] AS laps),
STRUCT("Murphy" AS name, [23.9, 26.0, 27.0, 26.0] AS laps),
STRUCT("Bosse" AS name, [23.6, 26.2, 26.5, 27.1] AS laps),
STRUCT("Rotich" AS name, [24.7, 25.6, 26.9, 26.4] AS laps),
STRUCT("Lewandowski" AS name, [25.0, 25.7, 26.3, 27.2] AS laps),
STRUCT("Kipketer" AS name, [23.2, 26.1, 27.3, 29.4] AS laps),
STRUCT("Berian" AS name, [23.7, 26.1, 27.0, 29.3] AS laps)]
AS participants)
SELECT
race,
(SELECT name
FROM UNNEST(participants)
ORDER BY (
SELECT SUM(duration)
FROM UNNEST(laps) AS duration) ASC
LIMIT 1) AS fastest_racer
FROM Races;
/*------+---------------*
| race | fastest_racer |
+------+---------------+
| 800M | Rudisha |
*------+---------------*/
Lancer des requêtes sur des champs de type ARRAY
dans un objet struct
Vous pouvez également obtenir des informations à partir de champs répétés imbriqués. Par exemple, l'instruction suivante renvoie le coureur qui a réalisé le tour de piste le plus rapide lors d'une course sur 800 m.
WITH Races AS (
SELECT "800M" AS race,
[STRUCT("Rudisha" AS name, [23.4, 26.3, 26.4, 26.1] AS laps),
STRUCT("Makhloufi" AS name, [24.5, 25.4, 26.6, 26.1] AS laps),
STRUCT("Murphy" AS name, [23.9, 26.0, 27.0, 26.0] AS laps),
STRUCT("Bosse" AS name, [23.6, 26.2, 26.5, 27.1] AS laps),
STRUCT("Rotich" AS name, [24.7, 25.6, 26.9, 26.4] AS laps),
STRUCT("Lewandowski" AS name, [25.0, 25.7, 26.3, 27.2] AS laps),
STRUCT("Kipketer" AS name, [23.2, 26.1, 27.3, 29.4] AS laps),
STRUCT("Berian" AS name, [23.7, 26.1, 27.0, 29.3] AS laps)]
AS participants)
SELECT
race,
(SELECT name
FROM UNNEST(participants),
UNNEST(laps) AS duration
ORDER BY duration ASC LIMIT 1) AS runner_with_fastest_lap
FROM Races;
/*------+-------------------------*
| race | runner_with_fastest_lap |
+------+-------------------------+
| 800M | Kipketer |
*------+-------------------------*/
Notez que la requête précédente utilise l'opérateur "virgule" (,
) pour exécuter une commande CROSS JOIN
implicite. Cela équivaut à l'exemple suivant, qui utilise CROSS JOIN
explicitement.
WITH Races AS (
SELECT "800M" AS race,
[STRUCT("Rudisha" AS name, [23.4, 26.3, 26.4, 26.1] AS laps),
STRUCT("Makhloufi" AS name, [24.5, 25.4, 26.6, 26.1] AS laps),
STRUCT("Murphy" AS name, [23.9, 26.0, 27.0, 26.0] AS laps),
STRUCT("Bosse" AS name, [23.6, 26.2, 26.5, 27.1] AS laps),
STRUCT("Rotich" AS name, [24.7, 25.6, 26.9, 26.4] AS laps),
STRUCT("Lewandowski" AS name, [25.0, 25.7, 26.3, 27.2] AS laps),
STRUCT("Kipketer" AS name, [23.2, 26.1, 27.3, 29.4] AS laps),
STRUCT("Berian" AS name, [23.7, 26.1, 27.0, 29.3] AS laps)]
AS participants)
SELECT
race,
(SELECT name
FROM UNNEST(participants)
CROSS JOIN UNNEST(laps) AS duration
ORDER BY duration ASC LIMIT 1) AS runner_with_fastest_lap
FROM Races;
/*------+-------------------------*
| race | runner_with_fastest_lap |
+------+-------------------------+
| 800M | Kipketer |
*------+-------------------------*/
L'aplatissement de tableaux avec CROSS JOIN
exclut les lignes contenant des tableaux vides ou NULL. Si vous souhaitez inclure ces lignes, utilisez LEFT JOIN
.
WITH Races AS (
SELECT "800M" AS race,
[STRUCT("Rudisha" AS name, [23.4, 26.3, 26.4, 26.1] AS laps),
STRUCT("Makhloufi" AS name, [24.5, 25.4, 26.6, 26.1] AS laps),
STRUCT("Murphy" AS name, [23.9, 26.0, 27.0, 26.0] AS laps),
STRUCT("Bosse" AS name, [23.6, 26.2, 26.5, 27.1] AS laps),
STRUCT("Rotich" AS name, [24.7, 25.6, 26.9, 26.4] AS laps),
STRUCT("Lewandowski" AS name, [25.0, 25.7, 26.3, 27.2] AS laps),
STRUCT("Kipketer" AS name, [23.2, 26.1, 27.3, 29.4] AS laps),
STRUCT("Berian" AS name, [23.7, 26.1, 27.0, 29.3] AS laps),
STRUCT("Nathan" AS name, ARRAY<FLOAT64>[] AS laps),
STRUCT("David" AS name, NULL AS laps)]
AS participants)
SELECT
name, sum(duration) AS finish_time
FROM Races CROSS JOIN Races.participants LEFT JOIN participants.laps AS duration
GROUP BY name;
/*-------------+--------------------*
| name | finish_time |
+-------------+--------------------+
| Murphy | 102.9 |
| Rudisha | 102.19999999999999 |
| David | NULL |
| Rotich | 103.6 |
| Makhloufi | 102.6 |
| Berian | 106.1 |
| Bosse | 103.4 |
| Kipketer | 106 |
| Nathan | NULL |
| Lewandowski | 104.2 |
*-------------+--------------------*/
Construire des tableaux
Vous pouvez créer un élément array à l'aide de littéraux ou de fonctions de tableau. Pour en savoir plus sur la construction de tableaux, consultez la section Type de tableau.
Créer des tableaux à partir de sous-requêtes
Une tâche courante lors de l'utilisation de tableaux consiste à convertir un résultat de sous-requête en tableau. En GoogleSQL, vous pouvez effectuer cette opération à l'aide de la fonction ARRAY()
.
Prenons l'exemple de l'opération suivante sur la table Sequences
:
WITH Sequences AS
(SELECT [0, 1, 1, 2, 3, 5] AS some_numbers
UNION ALL SELECT [2, 4, 8, 16, 32] AS some_numbers
UNION ALL SELECT [5, 10] AS some_numbers)
SELECT some_numbers,
ARRAY(SELECT x * 2
FROM UNNEST(some_numbers) AS x) AS doubled
FROM Sequences;
/*--------------------+---------------------*
| some_numbers | doubled |
+--------------------+---------------------+
| [0, 1, 1, 2, 3, 5] | [0, 2, 2, 4, 6, 10] |
| [2, 4, 8, 16, 32] | [4, 8, 16, 32, 64] |
| [5, 10] | [10, 20] |
*--------------------+---------------------*/
Cet exemple utilise une table nommée "Sequences". Cette table contient une colonne some_numbers
de type ARRAY<INT64>
.
La requête elle-même contient une sous-requête. Cette sous-requête sélectionne chaque ligne de la colonne some_numbers
et utilise UNNEST
pour renvoyer le tableau sous forme d'un ensemble de lignes. Ensuite, elle multiplie chaque valeur par deux, puis recombine les lignes dans un tableau à l'aide de l'opérateur ARRAY()
.
Filtrer des tableaux
L'exemple suivant utilise une clause WHERE
dans la sous-requête de l'opérateur ARRAY()
pour filtrer les lignes renvoyées.
WITH Sequences AS
(SELECT [0, 1, 1, 2, 3, 5] AS some_numbers
UNION ALL SELECT [2, 4, 8, 16, 32] AS some_numbers
UNION ALL SELECT [5, 10] AS some_numbers)
SELECT
ARRAY(SELECT x * 2
FROM UNNEST(some_numbers) AS x
WHERE x < 5) AS doubled_less_than_five
FROM Sequences;
/*------------------------*
| doubled_less_than_five |
+------------------------+
| [0, 2, 2, 4, 6] |
| [4, 8] |
| [] |
*------------------------*/
Notez à nouveau que la troisième ligne contient un tableau vide, car le tableau de la ligne d'origine correspondante ([5, 10]
) ne répondaient pas à l'exigence de filtre x < 5
.
Vous pouvez également filtrer des tableaux en utilisant SELECT DISTINCT
pour ne renvoyer que des éléments uniques au sein d'un tableau.
WITH Sequences AS
(SELECT [0, 1, 1, 2, 3, 5] AS some_numbers)
SELECT ARRAY(SELECT DISTINCT x
FROM UNNEST(some_numbers) AS x) AS unique_numbers
FROM Sequences;
/*-----------------*
| unique_numbers |
+-----------------+
| [0, 1, 2, 3, 5] |
*-----------------*/
Vous pouvez également filtrer des lignes de tableaux en utilisant le mot clé IN
. Ce mot clé filtre les lignes contenant des tableaux en déterminant si une valeur spécifique correspond à un élément du tableau.
WITH Sequences AS
(SELECT [0, 1, 1, 2, 3, 5] AS some_numbers
UNION ALL SELECT [2, 4, 8, 16, 32] AS some_numbers
UNION ALL SELECT [5, 10] AS some_numbers)
SELECT
ARRAY(SELECT x
FROM UNNEST(some_numbers) AS x
WHERE 2 IN UNNEST(some_numbers)) AS contains_two
FROM Sequences;
/*--------------------*
| contains_two |
+--------------------+
| [0, 1, 1, 2, 3, 5] |
| [2, 4, 8, 16, 32] |
| [] |
*--------------------*/
Notez à nouveau que la troisième ligne contient un tableau vide, car le tableau de la ligne d'origine correspondante ([5, 10]
) ne contenait pas 2
.
Analyser des tableaux
Pour vérifier si un tableau contient une valeur spécifique, utilisez l'opérateur IN
avec UNNEST
. Pour vérifier si un tableau contient une valeur correspondant à une condition, utilisez l'opérateur EXISTS
avec UNNEST
.
Rechercher des valeurs spécifiques
Pour rechercher une valeur spécifique dans un tableau, utilisez l'opérateur IN
avec UNNEST
.
Exemple
L'exemple suivant renvoie true
si le tableau contient le nombre 2.
SELECT 2 IN UNNEST([0, 1, 1, 2, 3, 5]) AS contains_value;
/*----------------*
| contains_value |
+----------------+
| true |
*----------------*/
Pour afficher les lignes d'une table dont la colonne de tableau contient une valeur spécifique, filtrez les résultats de IN UNNEST
à l'aide de la clause WHERE
.
Exemple
L'exemple suivant renvoie la valeur id
pour les lignes dans lesquelles la colonne de tableau contient la valeur 2.
WITH Sequences AS
(SELECT 1 AS id, [0, 1, 1, 2, 3, 5] AS some_numbers
UNION ALL SELECT 2 AS id, [2, 4, 8, 16, 32] AS some_numbers
UNION ALL SELECT 3 AS id, [5, 10] AS some_numbers)
SELECT id AS matching_rows
FROM Sequences
WHERE 2 IN UNNEST(Sequences.some_numbers)
ORDER BY matching_rows;
/*---------------*
| matching_rows |
+---------------+
| 1 |
| 2 |
*---------------*/
Rechercher des valeurs qui répondent à une condition
Pour rechercher dans un tableau des valeurs correspondant à une condition, utilisez UNNEST
pour renvoyer une table des éléments du tableau, WHERE
pour filtrer la table résultante dans une sous-requête et EXISTS
pour vérifier si la table filtrée contient des lignes.
Exemple
L'exemple suivant renvoie la valeur id
pour les lignes dans lesquelles la colonne de tableau contient des valeurs supérieures à 5.
WITH
Sequences AS (
SELECT 1 AS id, [0, 1, 1, 2, 3, 5] AS some_numbers
UNION ALL
SELECT 2 AS id, [2, 4, 8, 16, 32] AS some_numbers
UNION ALL
SELECT 3 AS id, [5, 10] AS some_numbers
)
SELECT id AS matching_rows
FROM Sequences
WHERE EXISTS(SELECT * FROM UNNEST(some_numbers) AS x WHERE x > 5);
/*---------------*
| matching_rows |
+---------------+
| 2 |
| 3 |
*---------------*/
Rechercher des valeurs de champ STRUCT
répondant à une condition
Pour rechercher dans un tableau de données STRUCT
un champ dont la valeur répond à une condition, utilisez UNNEST
pour renvoyer une table avec une colonne pour chaque champ STRUCT
, puis filtrez les lignes non correspondantes de la table à l'aide de WHERE EXISTS
.
Exemple
L'exemple suivant renvoie les lignes pour lesquelles la colonne de tableau contient un STRUCT
dont le champ b
possède une valeur supérieure à 3.
WITH
Sequences AS (
SELECT 1 AS id, [STRUCT(0 AS a, 1 AS b)] AS some_numbers
UNION ALL
SELECT 2 AS id, [STRUCT(2 AS a, 4 AS b)] AS some_numbers
UNION ALL
SELECT 3 AS id, [STRUCT(5 AS a, 3 AS b), STRUCT(7 AS a, 4 AS b)] AS some_numbers
)
SELECT id AS matching_rows
FROM Sequences
WHERE EXISTS(SELECT 1 FROM UNNEST(some_numbers) WHERE b > 3);
/*---------------*
| matching_rows |
+---------------+
| 2 |
| 3 |
*---------------*/
Tableaux et agrégation
Avec GoogleSQL, vous pouvez agréger des valeurs dans un tableau à l'aide de ARRAY_AGG()
.
WITH Fruits AS
(SELECT "apple" AS fruit
UNION ALL SELECT "pear" AS fruit
UNION ALL SELECT "banana" AS fruit)
SELECT ARRAY_AGG(fruit) AS fruit_basket
FROM Fruits;
/*-----------------------*
| fruit_basket |
+-----------------------+
| [apple, pear, banana] |
*-----------------------*/
Le tableau renvoyé par ARRAY_AGG()
est dans un ordre arbitraire, car l'ordre dans lequel la fonction concatène des valeurs n'est pas garanti. Pour trier les éléments du tableau, utilisez ORDER BY
. Par exemple :
WITH Fruits AS
(SELECT "apple" AS fruit
UNION ALL SELECT "pear" AS fruit
UNION ALL SELECT "banana" AS fruit)
SELECT ARRAY_AGG(fruit ORDER BY fruit) AS fruit_basket
FROM Fruits;
/*-----------------------*
| fruit_basket |
+-----------------------+
| [apple, banana, pear] |
*-----------------------*/
Vous pouvez également appliquer des fonctions d'agrégation telles que SUM()
aux éléments d'un tableau. Par exemple, la requête suivante renvoie la somme des éléments du tableau pour chaque ligne de la table Sequences
.
WITH Sequences AS
(SELECT [0, 1, 1, 2, 3, 5] AS some_numbers
UNION ALL SELECT [2, 4, 8, 16, 32] AS some_numbers
UNION ALL SELECT [5, 10] AS some_numbers)
SELECT some_numbers,
(SELECT SUM(x)
FROM UNNEST(s.some_numbers) AS x) AS sums
FROM Sequences AS s;
/*--------------------+------*
| some_numbers | sums |
+--------------------+------+
| [0, 1, 1, 2, 3, 5] | 12 |
| [2, 4, 8, 16, 32] | 62 |
| [5, 10] | 15 |
*--------------------+------*/
GoogleSQL accepte également une fonction d'agrégation, ARRAY_CONCAT_AGG()
, qui concatène les éléments d'une colonne de tableau sur plusieurs lignes.
WITH Aggregates AS
(SELECT [1,2] AS numbers
UNION ALL SELECT [3,4] AS numbers
UNION ALL SELECT [5, 6] AS numbers)
SELECT ARRAY_CONCAT_AGG(numbers) AS count_to_six_agg
FROM Aggregates;
/*--------------------------------------------------*
| count_to_six_agg |
+--------------------------------------------------+
| [1, 2, 3, 4, 5, 6] |
*--------------------------------------------------*/
Convertir des tableaux en chaînes
La fonction ARRAY_TO_STRING()
permet de convertir un ARRAY<STRING>
en une seule valeur STRING
ou un ARRAY<BYTES>
en une seule valeur BYTES
où la valeur résultante est la concaténation ordonnée des éléments du tableau.
Le deuxième argument est le séparateur que la fonction insérera entre les entrées pour produire le résultat. Il doit être du même type que les éléments du premier argument.
Exemple :
WITH Words AS
(SELECT ["Hello", "World"] AS greeting)
SELECT ARRAY_TO_STRING(greeting, " ") AS greetings
FROM Words;
/*-------------*
| greetings |
+-------------+
| Hello World |
*-------------*/
Le troisième argument facultatif remplace les valeurs NULL
dans le tableau d'entrée.
Si vous omettez cet argument, la fonction ignore les éléments de tableau
NULL
.Si vous fournissez une chaîne vide, la fonction insère un séparateur pour les éléments de tableau
NULL
.
Exemple :
SELECT
ARRAY_TO_STRING(arr, ".", "N") AS non_empty_string,
ARRAY_TO_STRING(arr, ".", "") AS empty_string,
ARRAY_TO_STRING(arr, ".") AS omitted
FROM (SELECT ["a", NULL, "b", NULL, "c", NULL] AS arr);
/*------------------+--------------+---------*
| non_empty_string | empty_string | omitted |
+------------------+--------------+---------+
| a.N.b.N.c.N | a..b..c. | a.b.c |
*------------------+--------------+---------*/
Combiner des tableaux
Dans certains cas, vous pouvez combiner plusieurs tableaux en un seul.
Pour ce faire, utilisez la fonction ARRAY_CONCAT()
.
SELECT ARRAY_CONCAT([1, 2], [3, 4], [5, 6]) AS count_to_six;
/*--------------------------------------------------*
| count_to_six |
+--------------------------------------------------+
| [1, 2, 3, 4, 5, 6] |
*--------------------------------------------------*/
Mettre à jour des tableaux
Prenons l'exemple de table suivant appelé arrays_table
. La première colonne de la table est un tableau d'entiers et la deuxième colonne contient deux tableaux d'entiers imbriqués.
WITH arrays_table AS (
SELECT
[1, 2] AS regular_array,
STRUCT([10, 20] AS first_array, [100, 200] AS second_array) AS nested_arrays
UNION ALL SELECT
[3, 4] AS regular_array,
STRUCT([30, 40] AS first_array, [300, 400] AS second_array) AS nested_arrays
)
SELECT * FROM arrays_table;
/*---------------*---------------------------*----------------------------*
| regular_array | nested_arrays.first_array | nested_arrays.second_array |
+---------------+---------------------------+----------------------------+
| [1, 2] | [10, 20] | [100, 200] |
| [3, 4] | [30, 40] | [130, 400] |
*---------------*---------------------------*----------------------------*/
Vous pouvez mettre à jour des tableaux dans une table à l'aide de l'instruction UPDATE
. L'exemple suivant insère le chiffre 5 dans la colonne regular_array
et insère les éléments du champ first_array
de la colonne nested_arrays
dans le champ second_array
:
UPDATE
arrays_table
SET
regular_array = ARRAY_CONCAT(regular_array, [5]),
nested_arrays.second_array = ARRAY_CONCAT(nested_arrays.second_array,
nested_arrays.first_array)
WHERE TRUE;
SELECT * FROM arrays_table;
/*---------------*---------------------------*----------------------------*
| regular_array | nested_arrays.first_array | nested_arrays.second_array |
+---------------+---------------------------+----------------------------+
| [1, 2, 5] | [10, 20] | [100, 200, 10, 20] |
| [3, 4, 5] | [30, 40] | [130, 400, 30, 40] |
*---------------*---------------------------*----------------------------*/
Compresser des tableaux
Vous pouvez fusionner deux tableaux de taille égale en un seul tableau composé de paires d'éléments provenant de tableaux d'entrée, issus de leurs positions correspondantes. Cette opération est parfois appelée compression.
Vous pouvez compresser des tableaux avec UNNEST
et WITH OFFSET
. Dans cet exemple, chaque paire de valeurs est stockée en tant que STRUCT
dans un tableau.
WITH
Combinations AS (
SELECT
['a', 'b'] AS letters,
[1, 2, 3] AS numbers
)
SELECT
ARRAY(
SELECT AS STRUCT
letters[SAFE_OFFSET(index)] AS letter,
numbers[SAFE_OFFSET(index)] AS number
FROM Combinations
CROSS JOIN
UNNEST(
GENERATE_ARRAY(
0,
LEAST(ARRAY_LENGTH(letters), ARRAY_LENGTH(numbers)) - 1)) AS index
ORDER BY index
);
/*------------------------------*
| pairs |
+------------------------------+
| [{ letter: "a", number: 1 }, |
| { letter: "b", number: 2 }] |
*------------------------------*/
Vous pouvez utiliser des tableaux d'entrée de longueurs différentes tant que la longueur du premier tableau est égale ou inférieure à celle du deuxième tableau. La longueur du tableau compressé correspondra à celle du tableau d'entrée le plus court.
Pour obtenir un tableau compressé qui inclut tous les éléments, même lorsque les tableaux d'entrée sont de longueurs différentes, remplacez LEAST
par GREATEST
. Les éléments de l'un des tableaux qui n'ont pas d'élément associé dans l'autre tableau seront associés à NULL
.
WITH
Combinations AS (
SELECT
['a', 'b'] AS letters,
[1, 2, 3] AS numbers
)
SELECT
ARRAY(
SELECT AS STRUCT
letters[SAFE_OFFSET(index)] AS letter,
numbers[SAFE_OFFSET(index)] AS number
FROM Combinations
CROSS JOIN
UNNEST(
GENERATE_ARRAY(
0,
GREATEST(ARRAY_LENGTH(letters), ARRAY_LENGTH(numbers)) - 1)) AS index
ORDER BY index
);
/*-------------------------------*
| pairs |
+-------------------------------+
| [{ letter: "a", number: 1 }, |
| { letter: "b", number: 2 }, |
| { letter: null, number: 3 }] |
*-------------------------------*/
Construire des tableaux de tableaux
GoogleSQL n'est pas compatible avec la construction directe de tableaux de tableaux. À la place, vous créez un tableau de structures, chaque structure contenant un champ de type ARRAY
. Pour illustrer cela, prenons pour exemple le tableau Points
suivant :
/*----------*
| point |
+----------+
| [1, 5] |
| [2, 8] |
| [3, 7] |
| [4, 1] |
| [5, 7] |
*----------*/
Supposons maintenant que vous vouliez créer un tableau composé de chaque point
de la table Points
. Pour ce faire, placez le tableau renvoyé par chaque ligne dans un objet STRUCT
, comme indiqué ci-dessous.
WITH Points AS
(SELECT [1, 5] AS point
UNION ALL SELECT [2, 8] AS point
UNION ALL SELECT [3, 7] AS point
UNION ALL SELECT [4, 1] AS point
UNION ALL SELECT [5, 7] AS point)
SELECT ARRAY(
SELECT STRUCT(point)
FROM Points)
AS coordinates;
/*-------------------*
| coordinates |
+-------------------+
| [{point: [1,5]}, |
| {point: [2,8]}, |
| {point: [5,7]}, |
| {point: [3,7]}, |
| {point: [4,1]}] |
*-------------------*/