1

I have been tring to unpivot a table from google sheets table like the one below into (EAV) or Date, ldap, Shift:

        Date    Ldap1   Ldap2   Ldap3 </p>
       2020-04-01   Shift A Shift B Shift C </p>
       2020-04-02   Shift A Shift B Shift C</p>
       2020-04-03   Shift A Shift B Shift C</p> 

My initial code (arranged from somewhere else) works but I need to perform this around 400 times as columns go up to 400. Any ideas to make this faster and more practical?




      SELECT date,  "ldap1" AS id_name, ldap1 AS id
      FROM yt_tns_vendor_ops_ham_cog_leads.workflow_test
      UNION ALL
      SELECT date,  "ldap2" AS id_name, ldap2 AS id 
      FROM yt_tns_vendor_ops_ham_cog_leads.workflow_test
      ORDER BY date, id_name

Result:

date    id_name id
2020-04-01  Ldap1   Shift A
2020-04-01  Ldap2   Shift B
2020-04-02  Ldap1   Shift A
2020-04-02  Ldap2   Shift B
2020-04-03  Ldap1   Shift A
2020-04-03  Ldap2   Shift B
2020-04-04  Ldap1   Shift A
2020-04-04  Ldap2   Shift B
2020-04-05  Ldap1   Shift A
2020-04-05  Ldap2   Shift B
2020-04-06  Ldap1   Shift A
2020-04-06  Ldap2   Shift B
2020-04-07  Ldap1   WO
2020-04-07  Ldap2   WO
2020-04-08  Ldap1   WO
2020-04-08  Ldap2   WO
2020-04-09  Ldap1   Shift A
2020-04-09  Ldap2   Shift B
2020-04-10  Ldap1   Shift A
2020-04-10  Ldap2   Shift B
2020-04-11  Ldap1   Shift A
2020-04-11  Ldap2   Shift B
2020-04-12  Ldap1   Shift A
2020-04-12  Ldap2   Shift B
2020-04-13  Ldap1   Shift A
2020-04-13  Ldap2   Shift B
2020-04-14  Ldap1   Shift A
2020-04-14  Ldap2   Shift B
2020-04-15  Ldap1   WO
2020-04-15  Ldap2   WO
2020-04-16  Ldap1   WO
2020-04-16  Ldap2   WO
2020-04-17  Ldap1   Shift A
2020-04-17  Ldap2   Shift B
2020-04-18  Ldap1   Shift A
nbk
  • 45,398
  • 8
  • 30
  • 47
  • Sorry guys. I am new on this and it seems the text above have been incorrectly formatted. Basically the result I got was what I needed but the issue is that I will need to repeate the process 400 times. – Diego Arnaldo Penayo Apr 27 '20 at 22:41
  • don't worry we do this all the time. follow the columns names a pattern, then do it un a stored procedure with a loo and a preprared statement. Else you have to grab the colum names form the https://stackoverflow.com/a/4165253/5193536 and loop over that – nbk Apr 27 '20 at 22:46

1 Answers1

2

Below is for BigQuery Standard SQL

#standardSQL
SELECT `date`,
  SPLIT(kv, ':')[OFFSET(0)] id_name,
  SPLIT(kv, ':')[OFFSET(1)] id
FROM `project.dataset.table` t,
UNNEST(SPLIT(REGEXP_REPLACE(TO_JSON_STRING(t), r'[{}"]', ''))) kv
WHERE SPLIT(kv, ':')[OFFSET(0)] != 'date'

if to apply to sample data from your question as in below example

#standardSQL
WITH `project.dataset.table` AS (
  SELECT DATE '2020-04-01' `date`, 'Shift A' ldap1, 'Shift B' ldap2,  'Shift C' ldap3 UNION ALL
  SELECT '2020-04-02', 'Shift A', 'Shift B',  'Shift C' UNION ALL
  SELECT '2020-04-03', 'Shift A', 'Shift B',  'Shift C' 
)
SELECT `date`,
  SPLIT(kv, ':')[OFFSET(0)] id_name,
  SPLIT(kv, ':')[OFFSET(1)] id
FROM `project.dataset.table` t,
UNNEST(SPLIT(REGEXP_REPLACE(TO_JSON_STRING(t), r'[{}"]', ''))) kv
WHERE SPLIT(kv, ':')[OFFSET(0)] != 'date'

result is

Row date        id_name id   
1   2020-04-01  ldap1   Shift A  
2   2020-04-01  ldap2   Shift B  
3   2020-04-01  ldap3   Shift C  
4   2020-04-02  ldap1   Shift A  
5   2020-04-02  ldap2   Shift B  
6   2020-04-02  ldap3   Shift C  
7   2020-04-03  ldap1   Shift A  
8   2020-04-03  ldap2   Shift B  
9   2020-04-03  ldap3   Shift C     

Above query can be further refactored (depends on your tastes)

#standardSQL
SELECT `date`, id_name, id
FROM `project.dataset.table` t,
UNNEST(SPLIT(REGEXP_REPLACE(TO_JSON_STRING(t), r'[{}"]', ''))) kv,
UNNEST([STRUCT(SPLIT(kv, ':')[OFFSET(0)] AS id_name, SPLIT(kv, ':')[OFFSET(1)] AS id)])
WHERE id_name != 'date'

this one avoids redundant parts and slightly less verbose

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