Work with arrays
In GoogleSQL for BigQuery, an array is an ordered list consisting of zero or more
values of the same data type. You can construct arrays of a simple data type,
such as INT64, or a complex data type, such as STRUCT. However,
arrays of arrays aren't supported. To learn more about the ARRAY
data type, including
NULL handling, see Array type.
With GoogleSQL, you can construct array literals,
build arrays from subqueries using the
ARRAY function,
and aggregate values into an array using the
ARRAY_AGG
function.
You can combine arrays using functions like
ARRAY_CONCAT(), and convert arrays to strings using ARRAY_TO_STRING().
Accessing array elements
Consider the following table called Sequences. This table contains
the column some_numbers of the ARRAY data type.
WITH
SequencesAS(
SELECT[0,1,1,2,3,5]ASsome_numbersUNIONALL
SELECT[2,4,8,16,32]UNIONALL
SELECT[5,10]
)
SELECT*FROMSequences
/*---------------------*
| some_numbers |
+---------------------+
| [0, 1, 1, 2, 3, 5] |
| [2, 4, 8, 16, 32] |
| [5, 10] |
*---------------------*/
To access array elements in the some_numbers column, specify which
type of indexing you want to use:
either index
or OFFSET(index) for
zero-based indexes, or ORDINAL(index) for
one-based indexes.
For example:
SELECT
some_numbers,
some_numbers[0]ASindex_0,
some_numbers[OFFSET(1)]ASoffset_1,
some_numbers[ORDINAL(1)]ASordinal_1
FROMSequences
/*--------------------+---------+----------+-----------*
| 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 |
*--------------------+---------+----------+-----------*/
Finding lengths
The ARRAY_LENGTH function returns the length of an array.
WITHSequencesAS
(SELECT[0,1,1,2,3,5]ASsome_numbers
UNIONALLSELECT[2,4,8,16,32]ASsome_numbers
UNIONALLSELECT[5,10]ASsome_numbers)
SELECTsome_numbers,
ARRAY_LENGTH(some_numbers)ASlen
FROMSequences;
/*--------------------+--------*
| some_numbers | len |
+--------------------+--------+
| [0, 1, 1, 2, 3, 5] | 6 |
| [2, 4, 8, 16, 32] | 5 |
| [5, 10] | 2 |
*--------------------+--------*/
Converting elements in an array to rows in a table
To convert an ARRAY into a set of rows, also known as "flattening," use the
UNNEST
operator. UNNEST takes an ARRAY and returns a table with a single row for
each element in the ARRAY.
Because UNNEST destroys the order of the ARRAY elements, you may
wish to restore order to the table. To do so, use the optional WITH OFFSET
clause to return an additional column with the offset for each array element,
then use the ORDER BY clause to order the rows by their offset.
Example
SELECT*
FROMUNNEST(['foo','bar','baz','qux','corge','garply','waldo','fred'])
ASelement
WITHOFFSETASoffset
ORDERBYoffset;
/*----------+--------*
| element | offset |
+----------+--------+
| foo | 0 |
| bar | 1 |
| baz | 2 |
| qux | 3 |
| corge | 4 |
| garply | 5 |
| waldo | 6 |
| fred | 7 |
*----------+--------*/
To flatten an entire column of type ARRAY while preserving the values of the other
columns in each row, use a correlated INNER JOIN to join
the table containing the ARRAY column to the UNNEST output of that ARRAY
column.
With a correlated join, the UNNEST operator
references the ARRAY typed column from each row in the source table, which
appears previously in the FROM clause. For each row N in the source table,
UNNEST flattens the ARRAY from row N into a set of rows containing the
ARRAY elements, and then a correlated INNER JOIN or CROSS JOIN combines
this new set of rows with the single row N from the source table.
Examples
The following example uses UNNEST to return a row for each
element in the array column. Because of the INNER JOIN, the id column
contains the id values for the row in Sequences that contains each number.
WITH
SequencesAS(
SELECT1ASid,[0,1,1,2,3,5]ASsome_numbers
UNIONALLSELECT2ASid,[2,4,8,16,32]ASsome_numbers
UNIONALLSELECT3ASid,[5,10]ASsome_numbers
)
SELECTid,flattened_numbers
FROMSequences
INNERJOINUNNEST(Sequences.some_numbers)ASflattened_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 |
*------+-------------------*/
Note that for correlated joins the UNNEST operator is optional and the
INNER JOIN can be expressed as a CROSS JOIN or a comma cross join. Using the
comma cross join shorthand notation, the previous example is consolidated as
follows:
WITH
SequencesAS(
SELECT1ASid,[0,1,1,2,3,5]ASsome_numbers
UNIONALLSELECT2ASid,[2,4,8,16,32]ASsome_numbers
UNIONALLSELECT3ASid,[5,10]ASsome_numbers
)
SELECTid,flattened_numbers
FROMSequences,Sequences.some_numbersASflattened_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 |
*------+-------------------*/
Querying nested arrays
If a table contains an ARRAY of STRUCTs, you can
flatten the ARRAY to query the fields of the STRUCT.
You can also flatten ARRAY type fields of STRUCT values.
Querying STRUCT elements in an array
The following example uses UNNEST with INNER JOIN to flatten an ARRAY of
STRUCTs.
WITH
RacesAS(
SELECT
"800M"ASrace,
[
STRUCT("Rudisha"ASname,[23.4,26.3,26.4,26.1]ASlaps),
STRUCT("Makhloufi"ASname,[24.5,25.4,26.6,26.1]ASlaps),
STRUCT("Murphy"ASname,[23.9,26.0,27.0,26.0]ASlaps),
STRUCT("Bosse"ASname,[23.6,26.2,26.5,27.1]ASlaps),
STRUCT("Rotich"ASname,[24.7,25.6,26.9,26.4]ASlaps),
STRUCT("Lewandowski"ASname,[25.0,25.7,26.3,27.2]ASlaps),
STRUCT("Kipketer"ASname,[23.2,26.1,27.3,29.4]ASlaps),
STRUCT("Berian"ASname,[23.7,26.1,27.0,29.3]ASlaps)
]ASparticipants
)
SELECT
race,
participant
FROMRacesASr
INNERJOINUNNEST(r.participants)ASparticipant;
/*------+---------------------------------------*
| 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]} |
*------+---------------------------------------*/
You can find specific information from repeated fields. For example, the following query returns the fastest racer in an 800M race.
Example
WITH
RacesAS(
SELECT
"800M"ASrace,
[
STRUCT("Rudisha"ASname,[23.4,26.3,26.4,26.1]ASlaps),
STRUCT("Makhloufi"ASname,[24.5,25.4,26.6,26.1]ASlaps),
STRUCT("Murphy"ASname,[23.9,26.0,27.0,26.0]ASlaps),
STRUCT("Bosse"ASname,[23.6,26.2,26.5,27.1]ASlaps),
STRUCT("Rotich"ASname,[24.7,25.6,26.9,26.4]ASlaps),
STRUCT("Lewandowski"ASname,[25.0,25.7,26.3,27.2]ASlaps),
STRUCT("Kipketer"ASname,[23.2,26.1,27.3,29.4]ASlaps),
STRUCT("Berian"ASname,[23.7,26.1,27.0,29.3]ASlaps)
]ASparticipants
)
SELECT
race,
(
SELECTname
FROMUNNEST(participants)
ORDERBY(SELECTSUM(duration)FROMUNNEST(laps)ASduration)ASC
LIMIT1
)ASfastest_racer
FROMRaces;
/*------+---------------*
| race | fastest_racer |
+------+---------------+
| 800M | Rudisha |
*------+---------------*/
Querying ARRAY-type fields in a struct
You can also get information from nested repeated fields. For example, the following statement returns the runner who had the fastest lap in an 800M race.
WITH
RacesAS(
SELECT
"800M"ASrace,
[
STRUCT("Rudisha"ASname,[23.4,26.3,26.4,26.1]ASlaps),
STRUCT("Makhloufi"ASname,[24.5,25.4,26.6,26.1]ASlaps),
STRUCT("Murphy"ASname,[23.9,26.0,27.0,26.0]ASlaps),
STRUCT("Bosse"ASname,[23.6,26.2,26.5,27.1]ASlaps),
STRUCT("Rotich"ASname,[24.7,25.6,26.9,26.4]ASlaps),
STRUCT("Lewandowski"ASname,[25.0,25.7,26.3,27.2]ASlaps),
STRUCT("Kipketer"ASname,[23.2,26.1,27.3,29.4]ASlaps),
STRUCT("Berian"ASname,[23.7,26.1,27.0,29.3]ASlaps)
]ASparticipants
)
SELECT
race,
(
SELECTname
FROMUNNEST(participants),UNNEST(laps)ASduration
ORDERBYdurationASC
LIMIT1
)ASrunner_with_fastest_lap
FROMRaces;
/*------+-------------------------*
| race | runner_with_fastest_lap |
+------+-------------------------+
| 800M | Kipketer |
*------+-------------------------*/
Notice that the preceding query uses the comma operator (,) to perform a cross
join and flatten the array. This is equivalent to using an explicit
CROSS JOIN, or the following example which uses an explicit INNER JOIN:
WITH
RacesAS(
SELECT"800M"ASrace,
[
STRUCT("Rudisha"ASname,[23.4,26.3,26.4,26.1]ASlaps),
STRUCT("Makhloufi"ASname,[24.5,25.4,26.6,26.1]ASlaps),
STRUCT("Murphy"ASname,[23.9,26.0,27.0,26.0]ASlaps),
STRUCT("Bosse"ASname,[23.6,26.2,26.5,27.1]ASlaps),
STRUCT("Rotich"ASname,[24.7,25.6,26.9,26.4]ASlaps),
STRUCT("Lewandowski"ASname,[25.0,25.7,26.3,27.2]ASlaps),
STRUCT("Kipketer"ASname,[23.2,26.1,27.3,29.4]ASlaps),
STRUCT("Berian"ASname,[23.7,26.1,27.0,29.3]ASlaps)
]ASparticipants
)
SELECT
race,
(
SELECTname
FROMUNNEST(participants)
INNERJOINUNNEST(laps)ASduration
ORDERBYdurationASCLIMIT1
)ASrunner_with_fastest_lap
FROMRaces;
/*------+-------------------------*
| race | runner_with_fastest_lap |
+------+-------------------------+
| 800M | Kipketer |
*------+-------------------------*/
Flattening arrays with INNER JOIN excludes rows that have empty or NULL
arrays. If you want to include these rows, use LEFT JOIN.
WITH
RacesAS(
SELECT
"800M"ASrace,
[
STRUCT("Rudisha"ASname,[23.4,26.3,26.4,26.1]ASlaps),
STRUCT("Makhloufi"ASname,[24.5,25.4,26.6,26.1]ASlaps),
STRUCT("Murphy"ASname,[23.9,26.0,27.0,26.0]ASlaps),
STRUCT("Bosse"ASname,[23.6,26.2,26.5,27.1]ASlaps),
STRUCT("Rotich"ASname,[24.7,25.6,26.9,26.4]ASlaps),
STRUCT("Lewandowski"ASname,[25.0,25.7,26.3,27.2]ASlaps),
STRUCT("Kipketer"ASname,[23.2,26.1,27.3,29.4]ASlaps),
STRUCT("Berian"ASname,[23.7,26.1,27.0,29.3]ASlaps),
STRUCT("Nathan"ASname,ARRAY<FLOAT64>[]ASlaps),
STRUCT("David"ASname,NULLASlaps)
]ASparticipants
)
SELECT
Participant.name,
SUM(duration)ASfinish_time
FROMRaces
INNERJOINRaces.participantsASParticipant
LEFTJOINParticipant.lapsASduration
GROUPBYname;
/*-------------+--------------------*
| 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 |
*-------------+--------------------*/
Constructing arrays
You can construct an array using array literals or array functions. To learn more about constructing arrays, see Array type.
Creating arrays from subqueries
A common task when working with arrays is turning a subquery result into an
array. In GoogleSQL, you can accomplish this using the
ARRAY() function.
For example, consider the following operation on the Sequences table:
WITHSequencesAS
(SELECT[0,1,1,2,3,5]ASsome_numbers
UNIONALLSELECT[2,4,8,16,32]ASsome_numbers
UNIONALLSELECT[5,10]ASsome_numbers)
SELECTsome_numbers,
ARRAY(SELECTx*2
FROMUNNEST(some_numbers)ASx)ASdoubled
FROMSequences;
/*--------------------+---------------------*
| 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] |
*--------------------+---------------------*/
This example starts with a table named Sequences. This table contains a column,
some_numbers, of type ARRAY<INT64>.
The query itself contains a subquery. This subquery selects each row in the
some_numbers column and uses
UNNEST to return the
array as a set of rows. Next, it multiplies each value by two, and then
re-combines the rows back into an array using the ARRAY() operator.
Filtering arrays
The following example uses a WHERE clause in the ARRAY() operator's subquery
to filter the returned rows.
WITHSequencesAS
(SELECT[0,1,1,2,3,5]ASsome_numbers
UNIONALLSELECT[2,4,8,16,32]ASsome_numbers
UNIONALLSELECT[5,10]ASsome_numbers)
SELECT
ARRAY(SELECTx*2
FROMUNNEST(some_numbers)ASx
WHEREx < 5)ASdoubled_less_than_five
FROMSequences;
/*------------------------*
| doubled_less_than_five |
+------------------------+
| [0, 2, 2, 4, 6] |
| [4, 8] |
| [] |
*------------------------*/
Notice that the third row contains an empty array, because the elements in the
corresponding original row ([5, 10]) didn't meet the filter requirement of
x < 5.
You can also filter arrays by using SELECT DISTINCT to return only
unique elements within an array.
WITHSequencesAS
(SELECT[0,1,1,2,3,5]ASsome_numbers)
SELECTARRAY(SELECTDISTINCTx
FROMUNNEST(some_numbers)ASx)ASunique_numbers
FROMSequences;
/*-----------------*
| unique_numbers |
+-----------------+
| [0, 1, 2, 3, 5] |
*-----------------*/
You can also filter rows of arrays by using the
IN keyword. This
keyword filters rows containing arrays by determining if a specific
value matches an element in the array.
WITHSequencesAS
(SELECT[0,1,1,2,3,5]ASsome_numbers
UNIONALLSELECT[2,4,8,16,32]ASsome_numbers
UNIONALLSELECT[5,10]ASsome_numbers)
SELECT
ARRAY(SELECTx
FROMUNNEST(some_numbers)ASx
WHERE2INUNNEST(some_numbers))AScontains_two
FROMSequences;
/*--------------------*
| contains_two |
+--------------------+
| [0, 1, 1, 2, 3, 5] |
| [2, 4, 8, 16, 32] |
| [] |
*--------------------*/
Notice again that the third row contains an empty array, because the array in
the corresponding original row ([5, 10]) didn't contain 2.
Scanning arrays
To check if an array contains a specific value, use the IN
operator with UNNEST. To check if an array contains a value
matching a condition, use the EXISTS operator with
UNNEST.
Scanning for specific values
To scan an array for a specific value, use the IN operator with UNNEST.
Example
The following example returns true if the array contains the number 2.
SELECT2INUNNEST([0,1,1,2,3,5])AScontains_value;
/*----------------*
| contains_value |
+----------------+
| true |
*----------------*/
To return the rows of a table where the array column contains a specific value,
filter the results of IN UNNEST using the WHERE clause.
Example
The following example returns the id value for the rows where the array
column contains the value 2.
WITHSequencesAS
(SELECT1ASid,[0,1,1,2,3,5]ASsome_numbers
UNIONALLSELECT2ASid,[2,4,8,16,32]ASsome_numbers
UNIONALLSELECT3ASid,[5,10]ASsome_numbers)
SELECTidASmatching_rows
FROMSequences
WHERE2INUNNEST(Sequences.some_numbers)
ORDERBYmatching_rows;
/*---------------*
| matching_rows |
+---------------+
| 1 |
| 2 |
*---------------*/
Scanning for values that satisfy a condition
To scan an array for values that match a condition, use UNNEST to return a
table of the elements in the array, use WHERE to filter the resulting table in
a subquery, and use EXISTS to check if the filtered table contains any rows.
Example
The following example returns the id value for the rows where the array
column contains values greater than 5.
WITH
SequencesAS(
SELECT1ASid,[0,1,1,2,3,5]ASsome_numbers
UNIONALL
SELECT2ASid,[2,4,8,16,32]ASsome_numbers
UNIONALL
SELECT3ASid,[5,10]ASsome_numbers
)
SELECTidASmatching_rows
FROMSequences
WHEREEXISTS(SELECT*FROMUNNEST(some_numbers)ASxWHEREx > 5);
/*---------------*
| matching_rows |
+---------------+
| 2 |
| 3 |
*---------------*/
Scanning for STRUCT field values that satisfy a condition
To search an array of STRUCT values for a field whose value matches a condition, use
UNNEST to return a table with a column for each STRUCT field, then filter
non-matching rows from the table using WHERE EXISTS.
Example
The following example returns the rows where the array column contains a
STRUCT whose field b has a value greater than 3.
WITH
SequencesAS(
SELECT1ASid,[STRUCT(0ASa,1ASb)]ASsome_numbers
UNIONALL
SELECT2ASid,[STRUCT(2ASa,4ASb)]ASsome_numbers
UNIONALL
SELECT3ASid,[STRUCT(5ASa,3ASb),STRUCT(7ASa,4ASb)]ASsome_numbers
)
SELECTidASmatching_rows
FROMSequences
WHEREEXISTS(SELECT1FROMUNNEST(some_numbers)WHEREb > 3);
/*---------------*
| matching_rows |
+---------------+
| 2 |
| 3 |
*---------------*/
Arrays and aggregation
With GoogleSQL, you can aggregate values into an array using
ARRAY_AGG().
WITHFruitsAS
(SELECT"apple"ASfruit
UNIONALLSELECT"pear"ASfruit
UNIONALLSELECT"banana"ASfruit)
SELECTARRAY_AGG(fruit)ASfruit_basket
FROMFruits;
/*-----------------------*
| fruit_basket |
+-----------------------+
| [apple, pear, banana] |
*-----------------------*/
The array returned by ARRAY_AGG() is in an arbitrary order, since the order in
which the function concatenates values isn't guaranteed. To order the array
elements, use ORDER BY. For example:
WITHFruitsAS
(SELECT"apple"ASfruit
UNIONALLSELECT"pear"ASfruit
UNIONALLSELECT"banana"ASfruit)
SELECTARRAY_AGG(fruitORDERBYfruit)ASfruit_basket
FROMFruits;
/*-----------------------*
| fruit_basket |
+-----------------------+
| [apple, banana, pear] |
*-----------------------*/
You can also apply aggregate functions such as SUM() to the elements in an
array. For example, the following query returns the sum of array elements for
each row of the Sequences table.
WITHSequencesAS
(SELECT[0,1,1,2,3,5]ASsome_numbers
UNIONALLSELECT[2,4,8,16,32]ASsome_numbers
UNIONALLSELECT[5,10]ASsome_numbers)
SELECTsome_numbers,
(SELECTSUM(x)
FROMUNNEST(s.some_numbers)ASx)ASsums
FROMSequencesASs;
/*--------------------+------*
| some_numbers | sums |
+--------------------+------+
| [0, 1, 1, 2, 3, 5] | 12 |
| [2, 4, 8, 16, 32] | 62 |
| [5, 10] | 15 |
*--------------------+------*/
GoogleSQL also supports an aggregate function, ARRAY_CONCAT_AGG(),
which concatenates the elements of an array column across rows.
WITHAggregatesAS
(SELECT[1,2]ASnumbers
UNIONALLSELECT[3,4]ASnumbers
UNIONALLSELECT[5,6]ASnumbers)
SELECTARRAY_CONCAT_AGG(numbers)AScount_to_six_agg
FROMAggregates;
/*--------------------------------------------------*
| count_to_six_agg |
+--------------------------------------------------+
| [1, 2, 3, 4, 5, 6] |
*--------------------------------------------------*/
Converting arrays to strings
The ARRAY_TO_STRING() function allows you to convert an ARRAY<STRING> to a
single STRING value or an ARRAY<BYTES> to a single BYTES value where the
resulting value is the ordered concatenation of the array elements.
The second argument is the separator that the function will insert between inputs to produce the output; this second argument must be of the same type as the elements of the first argument.
Example:
WITHWordsAS
(SELECT["Hello","World"]ASgreeting)
SELECTARRAY_TO_STRING(greeting," ")ASgreetings
FROMWords;
/*-------------*
| greetings |
+-------------+
| Hello World |
*-------------*/
The optional third argument takes the place of NULL values in the input
array.
If you omit this argument, then the function ignores
NULLarray elements.If you provide an empty string, the function inserts a separator for
NULLarray elements.
Example:
SELECT
ARRAY_TO_STRING(arr,".","N")ASnon_empty_string,
ARRAY_TO_STRING(arr,".","")ASempty_string,
ARRAY_TO_STRING(arr,".")ASomitted
FROM(SELECT["a",NULL,"b",NULL,"c",NULL]ASarr);
/*------------------+--------------+---------*
| non_empty_string | empty_string | omitted |
+------------------+--------------+---------+
| a.N.b.N.c.N | a..b..c. | a.b.c |
*------------------+--------------+---------*/
Combining arrays
In some cases, you might want to combine multiple arrays into a single array.
You can accomplish this using the ARRAY_CONCAT() function.
SELECTARRAY_CONCAT([1,2],[3,4],[5,6])AScount_to_six;
/*--------------------------------------------------*
| count_to_six |
+--------------------------------------------------+
| [1, 2, 3, 4, 5, 6] |
*--------------------------------------------------*/
Updating arrays
Consider the following table called arrays_table. The first column in the
table is an array of integers and the second column contains two nested arrays
of integers.
WITHarrays_tableAS(
SELECT
[1,2]ASregular_array,
STRUCT([10,20]ASfirst_array,[100,200]ASsecond_array)ASnested_arrays
UNIONALLSELECT
[3,4]ASregular_array,
STRUCT([30,40]ASfirst_array,[300,400]ASsecond_array)ASnested_arrays
)
SELECT*FROMarrays_table;
/*---------------*---------------------------*----------------------------*
| regular_array | nested_arrays.first_array | nested_arrays.second_array |
+---------------+---------------------------+----------------------------+
| [1, 2] | [10, 20] | [100, 200] |
| [3, 4] | [30, 40] | [130, 400] |
*---------------*---------------------------*----------------------------*/
You can update arrays in a table by using the UPDATE statement. The following
example inserts the number 5 into the regular_array column,
and inserts the elements from the first_array field of the nested_arrays
column into the second_array field:
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)
WHERETRUE;
SELECT*FROMarrays_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] |
*---------------*---------------------------*----------------------------*/
Zipping arrays
Given two arrays of equal size, you can merge them into a single array consisting of pairs of elements from input arrays, taken from their corresponding positions. This operation is sometimes called zipping.
You can zip arrays with UNNEST and WITH OFFSET. In this example, each value
pair is stored as a STRUCT in an array.
WITH
CombinationsAS(
SELECT
['a','b']ASletters,
[1,2,3]ASnumbers
)
SELECT
ARRAY(
SELECTASSTRUCT
letters[SAFE_OFFSET(index)]ASletter,
numbers[SAFE_OFFSET(index)]ASnumber
FROMCombinations
INNERJOIN
UNNEST(
GENERATE_ARRAY(
0,
LEAST(ARRAY_LENGTH(letters),ARRAY_LENGTH(numbers))-1))ASindex
ORDERBYindex
)ASpairs;
/*------------------------------*
| pairs |
+------------------------------+
| [{ letter: "a", number: 1 }, |
| { letter: "b", number: 2 }] |
*------------------------------*/
You can use input arrays of different lengths as long as the first array is equal to or less than the length of the second array. The zipped array will be the length of the shortest input array.
To get a zipped array that includes all the elements even when the input arrays
are different lengths, change LEAST to GREATEST. Elements of either array
that have no associated element in the other array will be paired with NULL.
WITH
CombinationsAS(
SELECT
['a','b']ASletters,
[1,2,3]ASnumbers
)
SELECT
ARRAY(
SELECTASSTRUCT
letters[SAFE_OFFSET(index)]ASletter,
numbers[SAFE_OFFSET(index)]ASnumber
FROMCombinations
INNERJOIN
UNNEST(
GENERATE_ARRAY(
0,
GREATEST(ARRAY_LENGTH(letters),ARRAY_LENGTH(numbers))-1))ASindex
ORDERBYindex
)ASpairs;
/*-------------------------------*
| pairs |
+-------------------------------+
| [{ letter: "a", number: 1 }, |
| { letter: "b", number: 2 }, |
| { letter: null, number: 3 }] |
*-------------------------------*/
Building arrays of arrays
GoogleSQL doesn't support building
arrays of arrays
directly. Instead, you must create an array of structs, with each struct
containing a field of type ARRAY. To illustrate this, consider the following
Points table:
/*----------*
| point |
+----------+
| [1, 5] |
| [2, 8] |
| [3, 7] |
| [4, 1] |
| [5, 7] |
*----------*/
Now, let's say you wanted to create an array consisting of each point in the
Points table. To accomplish this, wrap the array returned from each row in a
STRUCT, as shown below.
WITHPointsAS
(SELECT[1,5]ASpoint
UNIONALLSELECT[2,8]ASpoint
UNIONALLSELECT[3,7]ASpoint
UNIONALLSELECT[4,1]ASpoint
UNIONALLSELECT[5,7]ASpoint)
SELECTARRAY(
SELECTSTRUCT(point)
FROMPoints)
AScoordinates;
/*-------------------*
| coordinates |
+-------------------+
| [{point: [1,5]}, |
| {point: [2,8]}, |
| {point: [5,7]}, |
| {point: [3,7]}, |
| {point: [4,1]}] |
*-------------------*/