3
votes

I'm using big query and i want to create a job which populates a table with a "record" type columns. The data will be populated by a query - so how can i write a query which returns "record" type columns.

Thanks!

2
You have a low rate. Important on SO, you have to mark accepted answers by using the tick on the left of the posted answer, below the voting. This will increase your rate. See how this works by visinting this link: meta.stackoverflow.com/questions/5234/…Pentium10

2 Answers

3
votes

Somehow option proposed by Pentium10 never worked for me in GBQ UI or API Explorer.
I might be missing something

Meantime, the workaround I found is as in below example

SELECT location.state, location.city FROM JS(
  (      // input table
  SELECT NEST(CONCAT(state, ',', city)) AS locations
  FROM (
    SELECT state, city FROM 
    (SELECT 'florida' AS state, 'miami' AS city),
    (SELECT 'california' AS state, 'la' AS city),
    (SELECT 'romania' AS state, 'transylvania' AS city)
    ) 
  ),
  locations,     // input columns
  "[    // output schema
    {'name': 'location', 'type': 'RECORD',
     'mode': 'REPEATED',
     'fields': [
       {'name': 'state', 'type': 'STRING'},
       {'name': 'city', 'type': 'STRING'}
     ]    
    }
  ]",
  "function(row, emit){    // function 
    for (var i = 0; i < row.locations.length; i++) {
      var c = [];
      x = row.locations[i].split(',');
      t = {state:x[0], city:x[1]}
      c.push(t);
      emit({location: c});  
    };
  }"
)  

Please note:
you should set destination table with Allow Large Results and unchecked Flatten Results

Result from output table is (in JSON Mode)

[
  {
    "location": [
      {
        "state": "california",
        "city": "la"
      }
    ]
  },
  {
    "location": [
      {
        "state": "florida",
        "city": "miami"
      }
    ]
  },
  {
    "location": [
      {
        "state": "romania",
        "city": "transylvania"
      }
    ]
  }
]

Added to address some issue @AdiCohen has with his real example that he showed in his recent comments:

Q: my query has other columns besides the record column, but when i ran the query, they return as null. how can i create a table with both of the types?

SELECT amount, currency, location.state, location.city FROM JS( 
  ( // input table 
    SELECT NEST(CONCAT(state, ',', city)) AS locations, 
      SUM(amount) AS amount, MAX(currency) as currency 
    FROM ( 
      SELECT state, city, amount, currency, ROW_NUMBER() OVER() as grp FROM 
        (SELECT 'florida' AS state, 'miami' AS city, 'coins' AS currency, 40 AS amount), 
        (SELECT 'california' AS state, 'la' AS city, 'coins' AS currency, 40 AS amount), 
        (SELECT 'romania' AS state, 'transylvania' AS city,'coins' AS currency, 40 AS amount) 
    ) GROUP BY grp
  ), 
  amount, currency, locations, // input columns 
  "[ // output schema 
    {'name': 'location', 'type': 'RECORD', 'mode': 'REPEATED', 
    'fields': [ 
      {'name': 'state', 'type': 'STRING'}, 
      {'name': 'city', 'type': 'STRING'} 
    ] }, 
    { 'name': 'amount', 'type': 'INTEGER'}, 
    { 'name': 'currency', 'type': 'STRING'} 
  ]", 
  "function(row, emit) { // function 
    for (var i = 0; i < row.locations.length; i++) { 
      var c = []; 
      x = row.locations[i].split(','); 
      t = {state:x[0], city:x[1]} 
      c.push(t); 
      emit({amount: row.amount, currency: row.currency, location: c}); 
    }; 
  }"
) 

Output here is:

[
  {
    "amount": "40",
    "currency": "coins",
    "location_state": "romania",
    "location_city": "transylvania"
  },
  {
    "amount": "40",
    "currency": "coins",
    "location_state": "florida",
    "location_city": "miami"
  },
  {
    "amount": "40",
    "currency": "coins",
    "location_state": "california",
    "location_city": "la"
  }
]
1
votes

You need to use the dot notation to reflect the output as a RECORD example query:

select 
  'florida' as country.state, 
  'SFO' as country.city;

In this example country is the record and state|city are fields in the record.