Mit Arrays arbeiten

In GoogleSQL for BigQuery ist ein Array eine sortierte Liste aus null oder mehr Werten des gleichen Datentyps. Sie können Arrays mit einfachen Datentypen wie INT64 und komplexen Datentypen wie STRUCTs erstellen. Die aktuelle Ausnahme ist der ARRAY-Datentyp, denn Arrays von Arrays werden nicht unterstützt. Weitere Informationen zum Datentyp ARRAY, einschließlich der Behandlung von NULL, finden Sie unter Array-Typ.

Mit GoogleSQL können Sie Arrayliterale anlegen, mit der Funktion ARRAY Arrays aus Unterabfragen erstellen und mit der Funktion ARRAY_AGG Werte zu einem Array zusammenfassen.

Sie können Arrays mit Funktionen wie ARRAY_CONCAT() kombinieren und Arrays mit ARRAY_TO_STRING() in Strings konvertieren.

Auf Arrayelemente zugreifen

Betrachten Sie die folgende emulierte Tabelle mit dem Namen Sequences. Diese Tabelle enthält die Spalte some_numbers des Datentyps 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]             |
 *---------------------*/

Für den Zugriff auf Arrayelemente in der Spalte some_numbers müssen Sie angeben, welchen Indexierungstyp Sie verwenden möchten: index oder OFFSET(index) für nullbasierte Indexe oder ORDINAL(index) für einsbasierte Indexe.

Beispiel:

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         |
 *--------------------+---------+----------+-----------*/

Längenwerte suchen

Die Funktion ARRAY_LENGTH gibt die Länge eines Arrays zurück.

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      |
 *--------------------+--------*/

Elemente in einem Array in Zeilen einer Tabelle konvertieren

Verwenden Sie den Operator UNNEST, um ein ARRAY in einen Zeilensatz zu konvertieren. Dies wird auch als Vereinfachung bezeichnet. UNNEST gibt dann für das ARRAY eine Tabelle mit jeweils einer Zeile für jedes Element im ARRAY zurück.

Allerdings verändert UNNEST die Anordnung der ARRAY-Elemente. Falls Sie die ursprüngliche Anordnung innerhalb der Tabelle wiederherstellen möchten, tun Sie Folgendes: Verwenden Sie die optionale Klausel WITH OFFSET, um eine zusätzliche Spalte mit dem Versatz für jedes Arrayelement zurückzugeben. Verwenden Sie dann die Klausel ORDER BY, um die Zeilen nach deren Versatz zu ordnen.

Beispiel

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      |
 *----------+--------*/

Wenn Sie eine komplette Spalte von ARRAY-Werten vereinfachen und dabei in jeder Zeile die Werte der anderen Spalten beibehalten möchten, verwenden Sie INNER JOIN. Damit verknüpfen Sie die Tabelle, die die ARRAY-Spalte enthält, mit der UNNEST-Ausgabe dieser ARRAY-Spalte.

Bei einem korrelierten Join verweist der Operator UNNEST auf die typisierte ARRAY-Spalte aus jeder Zeile in der Quelltabelle, die zuvor in der FROM-Klausel angezeigt wurde. Für jede Zeile N in der Quelltabelle vereinfacht UNNEST das ARRAY aus Zeile N zu einem Zeilensatz, der die ARRAY-Elemente enthält. Anschließend wird dieser neue Zeilensatz mithilfe von INNER JOIN oder CROSS JOIN mit der einzelnen Zeile N aus der Quelltabelle kombiniert.

Beispiele

Im folgenden Beispiel wird mithilfe von UNNEST für jedes Element in der Arrayspalte eine Zeile zurückgegeben. Durch den INNER JOIN enthält die Spalte id die id-Werte für die Zeile in Sequences, die jede Zahl enthält.

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
INNER 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 |
 *------+-------------------*/

Der Operator UNNEST bei korrelierten Joins ist optional und INNER JOIN kann als ein CROSS JOIN oder ein Komma Cross Join ausgedrückt werden. Mit der Kurzschreibweise für Kreuzver joins mit Komma wird das vorherige Beispiel so konsolidiert:

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 |
 *------+-------------------*/

Verschachtelte Arrays abfragen

Enthält eine Tabelle ein ARRAY aus STRUCT-Werten, können Sie das ARRAY vereinfachen, um die Felder von STRUCT abzufragen. Sie können auch Felder vom Typ ARRAY mit Werten von STRUCT vereinfachen.

STRUCT-Elemente in einem Array abfragen

Im folgenden Beispiel wird UNNEST mit INNER JOIN verwendet, um ein ARRAY von STRUCT-Werten zu vereinfachen.

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
INNER 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]}      |
 *------+---------------------------------------*/

In wiederkehrenden Feldern finden Sie spezifische Informationen. Beispiel: Die folgende Abfrage gibt den schnellsten Läufer in einem Rennen über 800 Meter zurück.

Beispiel

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       |
 *------+---------------*/

Felder des Typs ARRAY in einem STRUCT abfragen

Sie können auch Informationen aus verschachtelten wiederkehrenden Feldern abrufen. Beispiel: Die folgende Anweisung gibt den Läufer zurück, der die schnellste Runde in dem 800 Meter-Lauf gelaufen ist.

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                |
 *------+-------------------------*/

Beachten Sie, dass bei der vorherigen Abfrage der Kommaoperator verwendet wurde (,), um ein Kreuzverweis-Join auszuführen und das Array zu vereinfachen. Dies entspricht der Verwendung eines expliziten CROSS JOIN oder dem folgenden Beispiel mit einem expliziten INNER 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)
      ] AS participants
  )
SELECT
  race,
  (
    SELECT name
    FROM UNNEST(participants)
    INNER 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                |
 *------+-------------------------*/

Durch das Vereinfachen von Arrays mit einem INNER JOIN werden Zeilen mit leeren oder NULL-Arrays ausgeschlossen. Wenn Sie diese Zeilen einbinden möchten, verwenden Sie 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
  Participant.name,
  SUM(duration) AS finish_time
FROM Races
INNER JOIN Races.participants AS Participant
LEFT JOIN Participant.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              |
 *-------------+--------------------*/

Arrays erstellen

Sie können ein Array mit Arrayliteralen oder Arrayfunktionen erstellen. Weitere Informationen zum Erstellen von Arrays finden Sie unter Array-Typ.

Arrays aus Unterabfragen erstellen

Eine häufige Aufgabe bei der Arbeit mit Arrays besteht darin, ein Unterabfrageergebnis zu einem Array zu machen. In GoogleSQL können Sie dies mithilfe von ARRAY() erreichen.

Ein Beispiel dafür ist der folgende Vorgang für die Tabelle 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]            |
 *--------------------+---------------------*/

Dieses Beispiel beginnt mit einer Tabelle namens „sequences“. Diese Tabelle enthält eine Spalte some_numbers vom Typ ARRAY<INT64>.

Die Abfrage selbst enthält eine Unterabfrage. Bei dieser Unterabfrage wird jede Zeile in der Spalte some_numbers ausgewählt und UNNEST verwendet, um das Array als Zeilensatz zurückzugeben. Anschließend wird jeder Wert mit zwei multipliziert und dann werden die Zeilen mithilfe des Operators ARRAY() wieder zu einem Array zusammengesetzt.

Arrays filtern

Im folgenden Beispiel wird in der Unterabfrage des Operators ARRAY() eine WHERE-Klausel verwendet, um die zurückgegebenen Zeilen zu filtern.

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]                 |
 | []                     |
 *------------------------*/

Beachten Sie, dass die dritte Zeile ein leeres Array enthält, da die Elemente in der entsprechenden ursprünglichen Zeile ([5, 10]) nicht die Filteranforderung von x < 5 erfüllen.

Sie können Arrays auch mit SELECT DISTINCT filtern, um nur einzelne Elemente innerhalb eines Arrays zurückzugeben.

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] |
 *-----------------*/

Sie können Zeilen von Arrays auch mithilfe des Schlüsselworts IN filtern. Dieses Schlüsselwort filtert Zeilen, die Arrays enthalten, indem bestimmt wird, ob ein spezifischer Wert mit einem Element in dem Array übereinstimmt.

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]  |
 | []                 |
 *--------------------*/

Wieder enthält die dritte Zeile ein leeres Array, weil das Array in der entsprechenden Originalzeile ([5, 10]) 2 nicht enthielt.

In Arrays suchen

Um in einem Array nach einem bestimmten Wert zu suchen, verwenden Sie den Operator IN mit UNNEST. Wenn Sie prüfen möchten, ob ein Array einen Wert enthält, der eine bestimmte Bedingung erfüllt, verwenden Sie den Operator EXISTS mit UNNEST.

Nach bestimmten Werten suchen

Verwenden Sie den Operator IN mit UNNEST, um ein Array nach einem bestimmten Wert zu durchsuchen.

Beispiel

Im folgenden Beispiel wird true zurückgegeben, wenn das Array die Zahl 2 enthält.

SELECT 2 IN UNNEST([0, 1, 1, 2, 3, 5]) AS contains_value;

/*----------------*
 | contains_value |
 +----------------+
 | true           |
 *----------------*/

Wenn die Zeilen einer Tabelle zurückgegeben werden sollen, deren Arrayspalte einen bestimmten Wert enthält, müssen Sie die Ergebnisse von IN UNNEST mit der Klausel WHERE filtern.

Beispiel

Im folgenden Beispiel wird der Wert id für die Zeilen zurückgegeben, in denen die Arrayspalte den Wert 2 enthält.

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             |
 *---------------*/

Nach Werten suchen, die eine Bedingung erfüllen

Wenn Sie in einem Array Werte suchen möchten, die eine Bedingung erfüllen, können Sie UNNEST verwenden, um eine Tabelle der Elemente im Array zurückzugeben. Mithilfe von WHERE können Sie die resultierende Tabelle über eine Unterabfrage filtern und mithilfe von EXISTS können Sie überprüfen, ob die gefilterte Tabelle Zeilen enthält.

Beispiel

Im folgenden Beispiel wird der Wert id für die Zeilen zurückgegeben, in denen die Arrayspalte Werte größer als 5 enthält.

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             |
 *---------------*/

Scannen nach STRUCT-Feldwerten, die eine Bedingung erfüllen

Wenn Sie ein Array von STRUCT nach Feldern durchsuchen möchten, deren Wert eine bestimmte Bedingung erfüllt, verwenden Sie UNNEST, um eine Tabelle mit jeweils einer Spalte für jedes STRUCT-Feld zurückzugeben, und filtern Sie dann nicht übereinstimmende Zeilen mit WHERE EXISTS aus der Tabelle heraus.

Beispiel

Im folgenden Beispiel werden die Zeilen zurückgegeben, in denen die Arrayspalte ein STRUCT enthält, dessen Feld b einen Wert größer als 3 hat.

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             |
 *---------------*/

Arrays und Aggregation

Mithilfe von ARRAY_AGG() können Sie in GoogleSQL Werte in einem Array zusammenfassen.

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] |
 *-----------------------*/

Das von ARRAY_AGG() zurückgegebene Array ist in einer beliebigen Reihenfolge angeordnet, weil die Reihenfolge, in der die Funktion Werte verkettet, nicht garantiert ist. Verwenden Sie zum Sortieren der Arrayelemente ORDER BY. Beispiel:

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] |
 *-----------------------*/

Sie können auch Aggregatfunktionen wie SUM() auf die Elemente in einem Array anwenden. Die folgende Abfrage gibt beispielsweise die Summe der Arrayelemente für jede Zeile der Tabelle Sequences zurück.

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 unterstützt auch eine Aggregatfunktion ARRAY_CONCAT_AGG(), die die Elemente einer Arrayspalte zeilenübergreifend verkettet.

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]                               |
 *--------------------------------------------------*/

Arrays in Strings umwandeln

Mit der Funktion ARRAY_TO_STRING() können Sie ein ARRAY<STRING> in einen einzelnen STRING-Wert oder ein ARRAY<BYTES> in einen einzelnen BYTES-Wert umwandeln, wobei der resultierende Wert die geordnete Verkettung der Arrayelemente ist.

Das zweite Argument ist das Trennzeichen, das für die Ausgabe zwischen den Eingaben einfügt wird. Dieses zweite Argument muss vom gleichen Typ wie die Elemente des ersten Arguments sein.

Beispiel:

WITH Words AS
  (SELECT ["Hello", "World"] AS greeting)
SELECT ARRAY_TO_STRING(greeting, " ") AS greetings
FROM Words;

/*-------------*
 | greetings   |
 +-------------+
 | Hello World |
 *-------------*/

Das optionale dritte Argument wird im Eingabearray für NULL-Werte verwendet.

  • Wenn Sie dieses Argument weglassen, werden NULL-Arrayelemente ignoriert.

  • Wenn Sie eine leere Zeichenfolge angeben, wird für NULL-Arrayelemente ein Trennzeichen eingefügt.

Beispiel:

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   |
 *------------------+--------------+---------*/

Arrays kombinieren

Gelegentlich sollen mehrere Arrays zu einem einzelnen Array kombiniert werden. Dies erreichen Sie mit der Funktion ARRAY_CONCAT().

SELECT ARRAY_CONCAT([1, 2], [3, 4], [5, 6]) AS count_to_six;

/*--------------------------------------------------*
 | count_to_six                                     |
 +--------------------------------------------------+
 | [1, 2, 3, 4, 5, 6]                               |
 *--------------------------------------------------*/

Arrays aktualisieren

Betrachten Sie die folgende Tabelle mit dem Namen arrays_table. Die erste Spalte in der Tabelle ist ein Array von Ganzzahlen und die zweite Spalte zwei verschachtelte Arrays mit Ganzzahlen.

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]                 |
 *---------------*---------------------------*----------------------------*/

Sie können Arrays in einer Tabelle mit der Anweisung UPDATE aktualisieren. Im folgenden Beispiel wird die Zahl 5 in die Spalte regular_array und die Elemente aus dem Feld first_array der Spalte nested_arrays in das Feld second_array eingefügt:

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]         |
 *---------------*---------------------------*----------------------------*/

Arrays komprimieren

Zwei Arrays gleicher Größe können Sie zu einem einzigen Array zusammenführen, das dann aus Paaren von Elementen aus Eingabearrays besteht, die aus den entsprechenden Positionen stammen. Dieser Vorgang wird manchmal als Komprimieren bezeichnet.

Sie können Arrays mit UNNEST und WITH OFFSET komprimieren. In diesem Beispiel wird jedes Wertepaar als STRUCT in einem Array gespeichert.

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
    INNER JOIN
      UNNEST(
        GENERATE_ARRAY(
          0,
          LEAST(ARRAY_LENGTH(letters), ARRAY_LENGTH(numbers)) - 1)) AS index
    ORDER BY index
  ) AS pairs;

/*------------------------------*
 | pairs                        |
 +------------------------------+
 | [{ letter: "a", number: 1 }, |
 |  { letter: "b", number: 2 }] |
 *------------------------------*/

Sie können Eingabearrays unterschiedlicher Länge verwenden, solange das erste Array gleich oder kleiner als das zweite Array ist. Das komprimierte Array entspricht dann der Länge des kürzesten Eingabearrays.

Wenn Sie ein komprimiertes Array mit allen Elementen erhalten möchten, selbst wenn die Eingabearrays unterschiedlicher Länge sind, ändern Sie LEAST in GREATEST. Elemente in einem der Arrays ohne verknüpfte Elemente im jeweils anderen Array werden mit NULL gekoppelt.

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
    INNER JOIN
      UNNEST(
        GENERATE_ARRAY(
          0,
          GREATEST(ARRAY_LENGTH(letters), ARRAY_LENGTH(numbers)) - 1)) AS index
    ORDER BY index
  ) AS pairs;

/*-------------------------------*
 | pairs                         |
 +-------------------------------+
 | [{ letter: "a", number: 1 },  |
 |  { letter: "b", number: 2 },  |
 |  { letter: null, number: 3 }] |
 *-------------------------------*/

Arrays von Arrays erstellen

In GoogleSQL können Arrays von Arrays nicht direkt erstellt werden. Stattdessen können Sie aber ein Array von Structs erstellen, in dem jedes Struct ein Feld vom Typ ARRAY enthält. Betrachten Sie zur Veranschaulichung die folgende Points-Tabelle:

/*----------*
 | point    |
 +----------+
 | [1, 5]   |
 | [2, 8]   |
 | [3, 7]   |
 | [4, 1]   |
 | [5, 7]   |
 *----------*/

Angenommen, Sie möchten ein Array aus allen point in der Tabelle Points erstellen. Fassen Sie zu diesem Zweck das aus jeder Zeile zurückgegebene Array wie unten dargestellt in einem STRUCT zusammen.

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]}]  |
 *-------------------*/