Shlomi Schwartz
Shlomi Schwartz

Reputation: 8903

Bigquery - Transpose Array into columns

The following query returns a list of key/value pairs:

SELECT ["name:apple", "color:red"] as fruit;

result:
enter image description here

Is there a way to transpose the data so the results would be:
enter image description here

Update I'm looking for a generalized solution, where the key and value and the array length of the results are unknown i.e: SELECT ["key0:val0", "key1:val1"...] as data;

Upvotes: 0

Views: 1886

Answers (3)

saifuddin778
saifuddin778

Reputation: 7277

This should be a quick way to achieve your results:

#standardSQL
with items as (
  select ["name:apple", "color:red"] p union all
  select ["name:orange", "color:orange"] UNION ALL
  select ["name:grapes", "color:green"]
),
arrayed as (
  select 
    array_agg(
       struct(
        if(split(p, ":")[offset(0)] = 'name', split(p, ":")[offset(1)], '') as name, 
        if(split(p, ":")[offset(0)] = 'color', split(p, ":")[offset(1)], '') as color 
      )
    ) item  from items, unnest(p) p
)
select 
  array((select i.name from unnest(item) i where i.name != '')) as name,
  array((select i.color from unnest(item) i where i.color != '')) as color
from arrayed

Upvotes: 2

Martin Weitzmann
Martin Weitzmann

Reputation: 4746

I guess the BigQuery way would be using sub-selects on the array:

WITH t AS (SELECT * FROM UNNEST([ 
    struct(['name:apple','color:red'] AS fruit), 
    struct(['name:pear','color:purple'] AS fruit)
  ]) )

SELECT
  (SELECT SPLIT(f, ':')[SAFE_OFFSET(1)] FROM t.fruit f WHERE SPLIT(f, ':')[SAFE_OFFSET(0)]='name') AS name,
  (SELECT SPLIT(f, ':')[SAFE_OFFSET(1)] FROM t.fruit f WHERE SPLIT(f, ':')[SAFE_OFFSET(0)]='color') AS color
FROM t

Upvotes: 1

Bobbylank
Bobbylank

Reputation: 1946

Not sure if there's a more succinct way to do this but this works

WITH CTE AS (
SELECT ["name:apple", "color:red"] as fruit
UNION ALL
SELECT ["name:pear", "color:green"]
),

CTE2 AS (
SELECT row_number() over () as rowNumber, fruit
FROM CTE
)

SELECT max(if(REGEXP_CONTAINS(fruit,'name:'),replace(fruit,'name:',''),null)) name,
  max(if(REGEXP_CONTAINS(fruit,'color:'),replace(fruit,'color:',''),null)) color
FROM CTE2,
UNNEST(fruit) as fruit
GROUP BY rowNumber

Upvotes: 0

Related Questions