

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 將巢狀陣列扁平化
<a name="flattening-arrays"></a>

使用巢狀陣列時，您經常需要將巢狀陣列元素展開至單一陣列，或將陣列展開至多個資料列。

## 使用扁平化函式
<a name="flattening-arrays-flatten-function"></a>

若要將巢狀陣列的元素扁平化至值的單一陣列，請使用 `flatten` 函數。此查詢會為陣列中的每個元素傳回一個資料列。

```
SELECT flatten(ARRAY[ ARRAY[1,2], ARRAY[3,4] ]) AS items
```

此查詢會傳回：

```
+-----------+
| items     |
+-----------+
| [1,2,3,4] |
+-----------+
```

## 使用 CROSS JOIN 和 UNNEST
<a name="flattening-arrays-cross-join-and-unnest"></a>

若要將陣列扁平化至多個資料列，請使用 `CROSS JOIN` 結合 `UNNEST` 運算子，如此範例所示：

```
WITH dataset AS (
  SELECT
    'engineering' as department,
    ARRAY['Sharon', 'John', 'Bob', 'Sally'] as users
)
SELECT department, names FROM dataset
CROSS JOIN UNNEST(users) as t(names)
```

此查詢會傳回：

```
+----------------------+
| department  | names  |
+----------------------+
| engineering | Sharon |
+----------------------|
| engineering | John   |
+----------------------|
| engineering | Bob    |
+----------------------|
| engineering | Sally  |
+----------------------+
```

若要將一系列的金鑰值組扁平化，請將選取的金鑰調換至資料欄，如此範例所示：

```
WITH
dataset AS (
  SELECT
    'engineering' as department,
     ARRAY[
      MAP(ARRAY['first', 'last', 'age'],ARRAY['Bob', 'Smith', '40']),
      MAP(ARRAY['first', 'last', 'age'],ARRAY['Jane', 'Doe', '30']),
      MAP(ARRAY['first', 'last', 'age'],ARRAY['Billy', 'Smith', '8'])
     ] AS people
  )
SELECT names['first'] AS
 first_name,
 names['last'] AS last_name,
 department FROM dataset
CROSS JOIN UNNEST(people) AS t(names)
```

此查詢會傳回：

```
+--------------------------------------+
| first_name | last_name | department  |
+--------------------------------------+
| Bob        | Smith     | engineering |
| Jane       | Doe       | engineering |
| Billy      | Smith     | engineering |
+--------------------------------------+
```

從員工清單中選擇具有最高組合評分的員工。`UNNEST` 可用於 `FROM` 子句，而不需先有`CROSS JOIN`，因為它是預設的聯結運算子，因此已隱含具備。

```
WITH
dataset AS (
  SELECT ARRAY[
    CAST(ROW('Sally', 'engineering', ARRAY[1,2,3,4]) AS ROW(name VARCHAR, department VARCHAR, scores ARRAY(INTEGER))),
    CAST(ROW('John', 'finance', ARRAY[7,8,9]) AS ROW(name VARCHAR, department VARCHAR, scores ARRAY(INTEGER))),
    CAST(ROW('Amy', 'devops', ARRAY[12,13,14,15]) AS ROW(name VARCHAR, department VARCHAR, scores ARRAY(INTEGER)))
  ] AS users
),
users AS (
 SELECT person, score
 FROM
   dataset,
   UNNEST(dataset.users) AS t(person),
   UNNEST(person.scores) AS t(score)
)
SELECT person.name, person.department, SUM(score) AS total_score FROM users
GROUP BY (person.name, person.department)
ORDER BY (total_score) DESC
LIMIT 1
```

此查詢會傳回：

```
+---------------------------------+
| name | department | total_score |
+---------------------------------+
| Amy  | devops     | 54          |
+---------------------------------+
```

從員工清單中選擇具有最高個別評分的員工。

```
WITH
dataset AS (
 SELECT ARRAY[
   CAST(ROW('Sally', 'engineering', ARRAY[1,2,3,4]) AS ROW(name VARCHAR, department VARCHAR, scores ARRAY(INTEGER))),
   CAST(ROW('John', 'finance', ARRAY[7,8,9]) AS ROW(name VARCHAR, department VARCHAR, scores ARRAY(INTEGER))),
   CAST(ROW('Amy', 'devops', ARRAY[12,13,14,15]) AS ROW(name VARCHAR, department VARCHAR, scores ARRAY(INTEGER)))
 ] AS users
),
users AS (
 SELECT person, score
 FROM
   dataset,
   UNNEST(dataset.users) AS t(person),
   UNNEST(person.scores) AS t(score)
)
SELECT person.name, score FROM users
ORDER BY (score) DESC
LIMIT 1
```

此查詢會傳回：

```
+--------------+
| name | score |
+--------------+
| Amy  | 15    |
+--------------+
```

### CROSS JOIN 和 UNNEST 的注意事項
<a name="flattening-arrays-cross-join-and-unnest-considerations"></a>

如果 `UNNEST` 在查詢中的一個或多個陣列上使用，且其中一個陣列是 `NULL`，則查詢不會傳回任何資料列。如果 `UNNEST` 在一個空字串陣列上使用，則會傳回空字串。

例如，在下列查詢中，由於第二個陣列為 Null，因此查詢不會傳回任何資料列。

```
SELECT 
    col1, 
    col2 
FROM UNNEST (ARRAY ['apples','oranges','lemons']) AS t(col1)
CROSS JOIN UNNEST (ARRAY []) AS t(col2)
```

在下面的範例中，第二個數組修改為包含一個空字串。針對每次資料列，查詢會傳回 `col1` 中的值，以及 `col2` 中的值的空字串。第二個陣列中的空字串為必要，以便傳回第一個陣列中的值。

```
SELECT 
    col1, 
    col2 
FROM UNNEST (ARRAY ['apples','oranges','lemons']) AS t(col1)
CROSS JOIN UNNEST (ARRAY ['']) AS t(col2)
```