2

I have a table with over 200 column names which are created with a temporary name like - custColum1 -custColum200.

I have a mapping table which contains a list of custColum1-custColumn200 to which name it has to be mapped with. For example

Table1(custColum1,custColum2) 
Mappingtable(tempColumnName,RealColumnName) 
data in mapping table be like 
(custColum1,Role_number)
(custColum2,Person_name)

I need to change table 1 to Table1(Role_number,Person_name). Note: I cannot create table1 with this name sincew I don't know which column would be mapped.

Was thinking if We could do something like creating a dynamic query and execute as shown below

SET @Sql = 'ALTER TABLE TABLE_NAME RENAME Column columnName'
           print  (@Sql)
           EXEC (@Sql)

Is there a way to do this in BigQuery? Any ideas will be great

Tamir Klein
  • 3,514
  • 1
  • 20
  • 38
Zcorps
  • 92
  • 1
  • 10
  • 1
    Bigquery doesn't support dynamic sql. See this answer for some options which might help you https://stackoverflow.com/a/54907722/1031958 – Tamir Klein Apr 04 '19 at 17:28

2 Answers2

4

Let’s assume simplified example as below

Table1
enter image description here

Mappingtable
enter image description here

The way I would approach your use case manually would be as below
First, assume we know in advance all mappings and we can assemble needed list manually and use it as below

#standardSQL
CREATE OR REPLACE TABLE `project.dataset.Table1` AS 
SELECT NULL AS Role_number, NULL AS Person_name  -- this line to be generated
  FROM (SELECT 1) WHERE FALSE UNION ALL
SELECT * FROM `project.dataset.Table1`  

Now, we need to “figure out” how to generate below line from the above query

'SELECT NULL AS Role_number, NULL AS Person_name' 

This can be done by running below query

#standardSQL
SELECT CONCAT('SELECT', STRING_AGG(CONCAT(' NULL AS ', RealColumnName) ORDER BY pos)) select_statement
FROM (
  SELECT TO_JSON_STRING(t) AS cols FROM `project.dataset.Table1` t LIMIT 1
), UNNEST(REGEXP_EXTRACT_ALL(cols, r'"(.*?)":')) col WITH OFFSET AS pos
LEFT JOIN `project.dataset.Mappingtable` ON tempColumnName = col  

This will produce exactly string we need

'SELECT NULL AS Role_number, NULL AS Person_name'   

So, now the question is how to add above dynamically built fragment into query that we are interested in!
Unfortunately, it is not doable as a one query purely within the BigQuery, but super simple task to accomplish in ANY client or tool of your choice

I can demonstrate how easily this can be done by non-technical user with the Tool of my choice – Magnus (part of Potens.io – Suite of tools for BigQuery)

Below is snapshot of Magnus Workflow with just two BigQuery Tasks, which reproduce exactly above steps

enter image description here

As you can see here:

In first Task we generate the statement with expected mapped Column names and assign result to parameter called var_columns_list (after workflow execution it will get expected value)

enter image description here

In second Task we just simply building dynamic sql using that parameter

Also, you can notice that instead of using plain reference to tables like project.dataset.Table1 and project.dataset.Mappingtable - I am using <var_project_dataset>.Table1 and <var_project_dataset>.Mappingtable and parameter var_project_dataset is set in parameters panel

After running that workflow ,we get expected result as shown below

enter image description here

While before execution it was

enter image description here

Obviously this is simplified example and it will work AS IS only if you have basic column types - no structs and no arrays. Still good news is this approach will easily handle 200 or even more columns you mentioned in your question.

Anyway, I think above example can be a good start for you!

Disclosure: I am an author and leader of Potens.io Team which is reflected in my profile. I am also Google Developer Expert for Cloud Platform and author of BigQuery Mate Chrome Extension

Mikhail Berlyant
  • 165,386
  • 8
  • 154
  • 230
1

BigQuery now supports Dynamic SQL. Building on Mikhail's answer, you can generate his query using:

EXECUTE IMMEDIATE format("""
   CREATE OR REPLACE TABLE dataset.Table1 AS 
   SELECT NULL AS %s, NULL AS %s
   FROM (SELECT 1) WHERE FALSE UNION ALL
   SELECT * FROM dataset.Table1  
""", 'custColum1', 'custColum2')

For more details, see this article: https://towardsdatascience.com/how-to-use-dynamic-sql-in-bigquery-8c04dcc0f0de

Lak
  • 3,876
  • 20
  • 34
  • This is excellent thanks. One question: where did you find the functionality of ```format () ```. I've never seen that in any bigquery before – FiercestJim Dec 24 '20 at 12:39
  • It's a built-in SQL string function: https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#format_string – Lak Dec 25 '20 at 19:17