> ## Documentation Index
> Fetch the complete documentation index at: https://docs.firebolt.io/llms.txt
> Use this file to discover all available pages before exploring further.

> Learn techniques to manipulate and transform arrays in Firebolt.

# Arrays

This section covers querying and manipulating arrays in Firebolt.

## Declaring ARRAY data types in table definitions

Array types are declared using `ARRAY(<type>)` where `<type>` can be any data type that Firebolt supports. This includes the `ARRAY` data type, so arrays can be arbitrarily nested.

If you load an array from a CSV file, the arrays in the CSV file must be enclosed in double quotes (`""`).

For example, if a CSV file contains a row containing `value1 , value2 , "[array_value3 , array_value4]"`, you can create a table using the following code to read `array_value3` and `array_value4` into `array_values`.

```sql theme={"theme":{"light":"css-variables","dark":"css-variables"}}
CREATE EXTERNAL TABLE IF NOT EXISTS array_example
    (
      value1 STRING,
      value2 STRING,
      array_values ARRAY(TEXT)
    )
    URL = 's3://path_to_your_data/'
    OBJECT_PATTERN = '*'
    TYPE = (csv);
```

Array literals are also supported. For example, the `SELECT` statement shown below is valid.

```sql theme={"theme":{"light":"css-variables","dark":"css-variables"}}
SELECT [1,2,3,4]
```

### Basis for examples

All examples in this topic are based on the `players` table from the example database. The `platforms` column is of type `ARRAY(TEXT)`.

<div className="query-window">
  ```
  SELECT playerid, nickname, platforms FROM players ORDER BY playerid LIMIT 5
  ```

  | playerid <span>int null</span> | nickname <span>text null</span> | platforms <span>array(text null) null</span>        |
  | :----------------------------- | :------------------------------ | :-------------------------------------------------- |
  | 1                              | steven70                        | \['Nintendo', 'PC']                                 |
  | 2                              | burchdenise                     | \['PC', 'Nintendo', 'iOS', 'Nintendo']              |
  | 3                              | stephanie86                     | \['Nintendo', 'PC']                                 |
  | 4                              | sabrina21                       | \['iOS', 'PC', 'PlayStation', 'PlayStation']        |
  | 5                              | kennethpark                     | \['Xbox', 'PlayStation', 'iOS', 'Nintendo', 'Xbox'] |

  <p><span>Rows: 5</span><span>Execution time: 14.26ms</span></p>
</div>

## Comparing values against arrays

You can compare a scalar value against the elements of an array using the [ANY/ALL (array)](/reference-sql/lexical-structure/any-all-array) quantified comparison operators. `ANY` returns `TRUE` if the comparison holds for at least one element, and `ALL` returns `TRUE` if it holds for every element.

<div className="query-window">
  ```
  SELECT 2 = ANY(ARRAY[1, 2, 3]) AS any_match,
         5 > ALL(ARRAY[1, 2, 3]) AS all_match;
  ```

  | any\_match <span>boolean null</span> | all\_match <span>boolean null</span> |
  | :----------------------------------- | :----------------------------------- |
  | True                                 | True                                 |

  <p><span>Rows: 1</span><span>Execution time: 8.31ms</span></p>
</div>

## Simple array functions

There are several fundamental functions that you can use to work with arrays, including [ARRAY\_LENGTH](/reference-sql/functions-reference/array/array-length), [ARRAY\_CONCAT](/reference-sql/functions-reference/array/array-concat), and [ARRAY\_FLATTEN](/reference-sql/functions-reference/array/flatten). See the respective reference for a full description. Brief examples are shown below.

### LENGTH example

`LENGTH` returns the number of elements in an array.

<div className="query-window">
  ```
  SELECT playerid, nickname, LENGTH(platforms) AS num_platforms
  FROM players
  ORDER BY playerid LIMIT 5
  ```

  | playerid <span>int null</span> | nickname <span>text null</span> | num\_platforms <span>int null</span> |
  | :----------------------------- | :------------------------------ | :----------------------------------- |
  | 1                              | steven70                        | 2                                    |
  | 2                              | burchdenise                     | 4                                    |
  | 3                              | stephanie86                     | 2                                    |
  | 4                              | sabrina21                       | 4                                    |
  | 5                              | kennethpark                     | 5                                    |

  <p><span>Rows: 5</span><span>Execution time: 15.38ms</span></p>
</div>

### ARRAY\_CONCAT example

`ARRAY_CONCAT` combines multiple arrays into a single array.

<div className="query-window">
  ```
  SELECT playerid, ARRAY_CONCAT(platforms, ['Android', 'Web']) AS all_platforms
  FROM players
  ORDER BY playerid LIMIT 3
  ```

  | playerid <span>int null</span> | all\_platforms <span>array(text null) null</span>        |
  | :----------------------------- | :------------------------------------------------------- |
  | 1                              | \['Nintendo', 'PC', 'Android', 'Web']                    |
  | 2                              | \['PC', 'Nintendo', 'iOS', 'Nintendo', 'Android', 'Web'] |
  | 3                              | \['Nintendo', 'PC', 'Android', 'Web']                    |

  <p><span>Rows: 3</span><span>Execution time: 11.37ms</span></p>
</div>

### ARRAY\_FLATTEN example

`ARRAY_FLATTEN` converts an ARRAY of ARRAYs into a single flattened ARRAY. Note that this operation flattens only one level of the array hierarchy.

<div className="query-window">
  ```
  SELECT ARRAY_FLATTEN([ [[1,2,3],[4,5]], [[2]] ]) AS flattened_array;
  ```

  | flattened\_array <span>array(array(int))</span> |
  | :---------------------------------------------- |
  | \[\[1, 2, 3], \[4, 5], \[2]]                    |

  <p><span>Rows: 1</span><span>Execution time: 7.58ms</span></p>
</div>

## Manipulating arrays with Lambda functions

Firebolt *Lambda functions* are a powerful tool that you can use on arrays to extract results. Lambda functions iteratively perform an operation on each element of one or more arrays. Arrays and the operation to perform are specified as arguments to the Lambda function.

### Lambda function general syntax

The general syntax pattern of a Lambda function is shown below. For detailed syntax and examples, see the reference topics for [Lambda functions](/reference-sql/functions-reference/lambda).

```
<LAMBDA_FUNC>(<arr1_var>[, <arr2_var>][, ...<arrN_var>] -> <operation>, <array1>[, <array2>][, ...<arrayN>])
```

| Parameter                                   | Description                                                                                                                                                                                                                                                                                                                           |
| :------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `<LAMBDA_FUNC>`                             | Any array function that accepts a Lambda expression as an argument. For a list, see [Lambda functions](/reference-sql/functions-reference/lambda).                                                                                                                                                                                    |
| `<arr1_var>[, <arr2_var>][, ...<arrN_var>]` | A list of one or more variables that you specify. The list is specified in the same order and must be the same length as the list of array expressions (`<array1>[, <array2>][, ...<arrayN>]`). At runtime, each variable contains an element of the corresponding array. The specified `<operation>` is performed for each variable. |
| `<operation>`                               | The operation that is performed for each element of the array. This is typically a function or Boolean expression.                                                                                                                                                                                                                    |
| `<array1>[, <array2>][, ...<arrayN>]`       | A comma-separated list of expressions, each of which evaluates to an `ARRAY` data type.                                                                                                                                                                                                                                               |

Optionally, you can enclose the variables in parentheses:

```
<LAMBDA_FUNC>((<arr1_var>[, <arr2_var>][, ...<arrN_var>]) -> <operation>, <array1>[, <array2>][, ...<arrayN>])
```

### Lambda function example: single array

Consider the following [TRANSFORM](/reference-sql/functions-reference/lambda/transform) array function that uses a single array variable and reference in the Lambda expression. This example applies the `UPPER` function to each element `p` in the `ARRAY`-typed column `platforms`. This converts each element in each `platforms` array to upper-case.

<div className="query-window">
  ```
  SELECT playerid, TRANSFORM(p -> UPPER(p), platforms) AS upper_platforms
  FROM players
  ORDER BY playerid LIMIT 5
  ```

  | playerid <span>int null</span> | upper\_platforms <span>array(text null) null</span> |
  | :----------------------------- | :-------------------------------------------------- |
  | 1                              | \['NINTENDO', 'PC']                                 |
  | 2                              | \['PC', 'NINTENDO', 'IOS', 'NINTENDO']              |
  | 3                              | \['NINTENDO', 'PC']                                 |
  | 4                              | \['IOS', 'PC', 'PLAYSTATION', 'PLAYSTATION']        |
  | 5                              | \['XBOX', 'PLAYSTATION', 'IOS', 'NINTENDO', 'XBOX'] |

  <p><span>Rows: 5</span><span>Execution time: 11.40ms</span></p>
</div>

### Lambda function example: ARRAY\_FIRST

[ARRAY\_FIRST](/reference-sql/functions-reference/lambda/array-first) returns the first element for which the Lambda predicate returns true, or NULL if no match is found.

<div className="query-window">
  ```
  SELECT playerid, nickname,
      ARRAY_FIRST((p) -> p = 'iOS', platforms) AS first_ios
  FROM players
  ORDER BY playerid LIMIT 5
  ```

  | playerid <span>int null</span> | nickname <span>text null</span> | first\_ios <span>text null</span> |
  | :----------------------------- | :------------------------------ | :-------------------------------- |
  | 1                              | steven70                        | NULL                              |
  | 2                              | burchdenise                     | iOS                               |
  | 3                              | stephanie86                     | NULL                              |
  | 4                              | sabrina21                       | iOS                               |
  | 5                              | kennethpark                     | iOS                               |

  <p><span>Rows: 5</span><span>Execution time: 12.11ms</span></p>
</div>

Optionally, you can omit the parentheses around the variables:

```sql theme={"theme":{"light":"css-variables","dark":"css-variables"}}
SELECT playerid, nickname,
    ARRAY_FIRST(p -> p = 'iOS', platforms) AS first_ios
FROM players
ORDER BY playerid LIMIT 5
```

### Lambda function example: multiple arrays

[ARRAY\_SORT](/reference-sql/functions-reference/array/array-sort) sorts one array by another. One array represents the values and the other represents the sort order.

The example below sorts the first array by the positions defined in the second array.

<div className="query-window">
  ```
  SELECT ARRAY_SORT((x, y) -> y, ['A', 'B', 'C'], [3, 2, 1]) AS res;
  ```

  | res <span>array(text)</span> |
  | :--------------------------- |
  | \['C', 'B', 'A']             |

  <p><span>Rows: 1</span><span>Execution time: 5.27ms</span></p>
</div>

Optionally, you can omit the parentheses around the variables:

```sql theme={"theme":{"light":"css-variables","dark":"css-variables"}}
SELECT ARRAY_SORT(x, y -> y, ['A', 'B', 'C'], [3, 2, 1]) AS res;
```

## UNNEST

You might want to transform a nested array structure to a standard tabular format. `UNNEST` serves this purpose.

[UNNEST](/reference-sql/commands/queries/select#unnest) is a table-valued function (TVF) that transforms an input row containing an array into a set of rows.
`UNNEST` unfolds the elements of the array and duplicates all other columns found in the `SELECT` clause for each array element.
If the input array is empty, the corresponding row is eliminated.

You can use a single `UNNEST` command to unnest several arrays if the arrays are the same length.

Multiple `UNNEST` statements in a single `FROM` clause result in a Cartesian product. Each element in the first array has a record in the result set corresponding to each element in the second array.

### Example: single UNNEST with single ARRAY-typed column

The following example unnests the `platforms` column from the `players` table.

<div className="query-window">
  ```
  SELECT playerid, nickname, platform
  FROM players, UNNEST(platforms) AS r(platform)
  ORDER BY playerid, platform LIMIT 8
  ```

  | playerid <span>int null</span> | nickname <span>text null</span> | platform <span>text null</span> |
  | :----------------------------- | :------------------------------ | :------------------------------ |
  | 1                              | steven70                        | Nintendo                        |
  | 1                              | steven70                        | PC                              |
  | 2                              | burchdenise                     | Nintendo                        |
  | 2                              | burchdenise                     | Nintendo                        |
  | 2                              | burchdenise                     | PC                              |
  | 2                              | burchdenise                     | iOS                             |
  | 3                              | stephanie86                     | Nintendo                        |
  | 3                              | stephanie86                     | PC                              |

  <p><span>Rows: 8</span><span>Execution time: 7.65ms</span></p>
</div>

### Example: single UNNEST using multiple ARRAY-typed columns

The following query specifies both the `platforms` column and `ARRAY_ENUMERATE(platforms)` to unnest, pairing each element with its position.

<div className="query-window">
  ```
  SELECT playerid, platform, idx
  FROM players, UNNEST(platforms, ARRAY_ENUMERATE(platforms)) AS r(platform, idx)
  ORDER BY playerid, idx LIMIT 8
  ```

  | playerid <span>int null</span> | platform <span>text null</span> | idx <span>int</span> |
  | :----------------------------- | :------------------------------ | :------------------- |
  | 1                              | Nintendo                        | 1                    |
  | 1                              | PC                              | 2                    |
  | 2                              | PC                              | 1                    |
  | 2                              | Nintendo                        | 2                    |
  | 2                              | iOS                             | 3                    |
  | 2                              | Nintendo                        | 4                    |
  | 3                              | Nintendo                        | 1                    |
  | 3                              | PC                              | 2                    |

  <p><span>Rows: 8</span><span>Execution time: 6.62ms</span></p>
</div>

### Example: multiple UNNEST clauses resulting in a Cartesian product

The following query, while valid, creates a Cartesian product.

<div className="query-window">
  ```
  SELECT playerid, p1, p2
  FROM players,
      UNNEST(platforms) AS r1(p1),
      UNNEST(platforms) AS r2(p2)
  WHERE playerid = 1
  ORDER BY p1, p2
  ```

  | playerid <span>int</span> | p1 <span>text null</span> | p2 <span>text null</span> |
  | :------------------------ | :------------------------ | :------------------------ |
  | 1                         | Nintendo                  | Nintendo                  |
  | 1                         | Nintendo                  | PC                        |
  | 1                         | PC                        | Nintendo                  |
  | 1                         | PC                        | PC                        |

  <p><span>Rows: 4</span><span>Execution time: 12.33ms</span></p>
</div>

### Example: error on UNNEST of multiple arrays with different lengths

The following query is **invalid** and will result in an error as the `platforms` and the literal two-element arrays have different lengths.

```sql theme={"theme":{"light":"css-variables","dark":"css-variables"}}
SELECT playerid, platform, x
FROM players, UNNEST(platforms, [1, 2]) AS r(platform, x);
```

## ARRAY input and output syntax

`ARRAY` values can be converted from and to `TEXT`. This happens, for example, when an explicit `CAST` is added to a query, or when `ARRAY` values are (de-)serialized in a `COPY` statement.

### Converting ARRAY to TEXT

Broadly, the `TEXT` representation of an `ARRAY` value starts with an opening curly brace (`{`). This is followed by the `TEXT` representations of the individual array elements separated by commas (`,`).
It ends with a closing curly brace (`}`). `NULL` array elements are represented by the literal string `NULL`. For example, the query

<div className="query-window">
  ```
  SELECT
      CAST([1,2,3,4,NULL] AS TEXT)
  ```

  | array <span>text</span> |
  | :---------------------- |
  | \{1,2,3,4,NULL}         |

  <p><span>Rows: 1</span><span>Execution time: 5.55ms</span></p>
</div>

When converting `ARRAY` values containing `TEXT` elements to `TEXT`, some additional rules apply. Specifically, array elements are enclosed by double quotes (`"`) in the following cases:

* The array element is an empty string.
* The array element contains curly or square braces (`{`,`[`,`]`,`}`), commas (`,`), double quotes (`"`), backslashes (`\`), or white space.
* The array element matches the word `NULL` (case-insensitively).

Additionally, double quotes and backslashes embedded in array elements will be backslash-escaped. For example, the query

```sql theme={"theme":{"light":"css-variables","dark":"css-variables"}}
SELECT
    CAST(['1','2','3','4',NULL,'','{impostor,array}','["impostor","array","back\slash"]',' padded and spaced ', 'only spaced', 'null'] AS TEXT)
```

returns the `TEXT` value `'{1,2,3,4,NULL,"","{impostor,array}","[\"impostor\",\"array\",\"back\\slash\"]"," padded and spaced ","only spaced","null"}'`.

### Converting TEXT to ARRAY

When converting the `TEXT` representation of an array back to `ARRAY`, the same quoting and escaping rules as above apply. Unquoted whitespace surrounding array elements is trimmed, but whitespace
contained within array elements is preserved. The array elements themselves are converted according to the conversion rules for the requested array element type. For example, the query

```sql theme={"theme":{"light":"css-variables","dark":"css-variables"}}
SELECT
    CAST('{1, 2, 3, 4, null, "", "{impostor,array}", "[\"impostor\",\"array\",\"back\\slash\"]", " padded and spaced ", "null",   unquoted padded and spaced   }' AS ARRAY(TEXT))
```

returns the `ARRAY(TEXT)` value `[1,2,3,4,NULL,'','{impostor,array}','["impostor","array","back\slash"]',' padded and spaced ','null','unquoted padded and spaced']`.

It is also possible to enclose arrays with square braces (`[` and `]`) instead of curly braces (`{` and `}`) when converting from `TEXT` to `ARRAY`. For example, the query

<div className="query-window">
  ```
  SELECT
      CAST('[1, 2, 3, 4, NULL]' AS ARRAY(INTEGER))
  ```

  | ?column? <span>array(int null)</span> |
  | :------------------------------------ |
  | \[1, 2, 3, 4, NULL]                   |

  <p><span>Rows: 1</span><span>Execution time: 7.62ms</span></p>
</div>

### Nested ARRAYs

Finally, the same procedure applies when converting nested `ARRAY` values from and to `TEXT`. For example, the query

<div className="query-window">
  ```
  SELECT
      CAST([NULL,[],[NULL],[1,2],[3,4]] AS TEXT)
  ```

  | array <span>text</span>           |
  | :-------------------------------- |
  | \{NULL,\{},\{NULL},\{1,2},\{3,4}} |

  <p><span>Rows: 1</span><span>Execution time: 6.04ms</span></p>
</div>

The following query converts back from `TEXT` to `ARRAY(ARRAY(INTEGER))`:

<div className="query-window">
  ```
  SELECT
      CAST('{NULL,{},{1,2},{3,4}}' AS ARRAY(ARRAY(INTEGER)))
  ```

  | ?column? <span>array(array(int null) null)</span> |
  | :------------------------------------------------ |
  | \[NULL, \[], \[1, 2], \[3, 4]]                    |

  <p><span>Rows: 1</span><span>Execution time: 5.63ms</span></p>
</div>
