

# ネストされた配列をフラット化する
<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` がクエリ内の 1 つ以上の配列で使用され、配列の 1 つが `NULL` である場合、クエリは行を返しません。空の文字列の配列に `UNNEST` を使用すると、空の文字列が返されます。

例えば、次のクエリでは、2 番目の配列が Null であるため、クエリは行を返しません。

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

次の例では、2 番目の配列が空の文字列を含むように変更されています。クエリは各行について、`col1` の値を返し、`col2` の値では空の文字列を返します。1 番目の配列の値を返すには、2 番目の配列の空の文字列が必要です。

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