Ao trabalhar com matrizes aninhadas, você normalmente precisa expandir elementos de matriz aninhados para uma única matriz ou expandir a matriz para várias linhas.
Usar a função de nivelamento
Para nivelar elementos de uma matriz aninhada em uma única matriz de valores, use a função flatten
. Essa consulta retorna uma linha para cada elemento na matriz.
SELECT flatten(ARRAY[ ARRAY[1,2], ARRAY[3,4] ]) AS items
Essa consulta retorna:
+-----------+
| items |
+-----------+
| [1,2,3,4] |
+-----------+
Usar CROSS JOIN e UNNEST
Para nivelar uma matriz em várias linhas, use CROSS JOIN
com o operador UNNEST
, como neste exemplo:
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)
Essa consulta retorna:
+----------------------+
| department | names |
+----------------------+
| engineering | Sharon |
+----------------------|
| engineering | John |
+----------------------|
| engineering | Bob |
+----------------------|
| engineering | Sally |
+----------------------+
Para nivelar uma matriz de pares chave/valor, transpor chaves selecionadas para colunas, como neste exemplo:
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)
Essa consulta retorna:
+--------------------------------------+
| first_name | last_name | department |
+--------------------------------------+
| Bob | Smith | engineering |
| Jane | Doe | engineering |
| Billy | Smith | engineering |
+--------------------------------------+
Em uma lista de funcionários, selecione o funcionário com a maior pontuação combinada. UNNEST
pode ser usado na cláusula FROM
sem um CROSS JOIN
anterior pois ele é o operador de junção padrão e, portanto, implícito.
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
Essa consulta retorna:
+---------------------------------+
| name | department | total_score |
+---------------------------------+
| Amy | devops | 54 |
+---------------------------------+
Em uma lista de funcionários, selecione o funcionário com a pontuação individual mais alta.
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
Essa consulta retorna:
+--------------+
| name | score |
+--------------+
| Amy | 15 |
+--------------+
Considerações sobre CROSS JOIN e UNNEST
Se a função UNNEST
for usada em uma ou mais matrizes na consulta e uma das matrizes for NULL
, a consulta não retornará nenhuma linha. Se a função UNNEST
for usada em uma matriz que é uma string vazia, a string vazia será retornada.
Por exemplo, na consulta apresentada a seguir, como a segunda matriz é nula, a consulta não retorna nenhuma linha.
SELECT
col1,
col2
FROM UNNEST (ARRAY ['apples','oranges','lemons']) AS t(col1)
CROSS JOIN UNNEST (ARRAY []) AS t(col2)
No próximo exemplo, a segunda matriz foi modificada para conter uma string vazia. Para cada linha, a consulta retorna o valor em col1
e uma string vazia para o valor em col2
. A string vazia na segunda matriz é necessária para que os valores na primeira matriz sejam retornados.
SELECT
col1,
col2
FROM UNNEST (ARRAY ['apples','oranges','lemons']) AS t(col1)
CROSS JOIN UNNEST (ARRAY ['']) AS t(col2)