Написание скрипта SQL, который получает список всех столбцов в BigQuery и вставляет их в запрос - PullRequest
1 голос
/ 13 апреля 2020

У меня есть такая таблица:

[ID]  [Country_Region]  [Date1]  [Date2]  [Date3] ... [Date150]

Я написал запрос SQL в BigQuery, который возвращает набор данных, подобный этому:

[ID] [Country_Region] [Date.ColumnName] [Date.Value] 
-----------------------------------------------------
 1    China           _1_22_20           12
 2    China           _1_23_20           34
 [3   China           _1_24_20           54] <----- I want this row and all the next ones to appear as well

Мой SQL запрос:

WITH timestamped_table AS 
(
    SELECT
        Country_Region,
        [STRUCT<timestamp STRING, timestamp_value INT64>
        ('2020-2-22', _2_22_20),
        ('2020-2-23', _2_23_20)] AS timestamp_data
    FROM
        `username.bq_timeseries_covid19.recovered_global` 
    WHERE
        Country_Region = 'China' AND Province_State = 'Zhejiang'
)
SELECT
    Country_Region, timestamp
FROM
    timestamped_table
CROSS JOIN
    UNNEST(timestamped_table.timestamp_data) AS timestamp

Теперь единственная проблема, с которой я столкнулся, заключается в том, что мне нужно расширить эти строки из запроса:

STRUCT<timestamp STRING, timestamp_value INT64>
        ('2020-2-22', _2_22_20),
        ('2020-2-23', _2_23_20)

, чтобы они включали все столбцы даты.

Я думаю, что это будет что-то вроде этого, если я буду расширять его с помощью какого-то сценария (что, я думаю, не лучшая идея?):

STRUCT<timestamp STRING, timestamp_value INT64>
        for column in get_date_columns():
        (timestamp_from_columnname(), column)

Я думаю, что написание SQL сценария / функция была бы лучше, но я не знаю, как начать с этого точно

Ответы [ 2 ]

2 голосов
/ 13 апреля 2020

Ниже для BigQuery Standard SQL и не требует явного перечисления столбцов независимо от того, сколько у вас столбцов - 50, 50 или 150 - он должен работать без каких-либо изменений в приведенном ниже коде

#standardSQL
SELECT id, Country_Region, 
  STRUCT(
      SPLIT(kv,':')[OFFSET(0)] AS ColumnName, 
      SPLIT(kv,':')[OFFSET(1)] AS Value
  ) AS `Date`
FROM `project.dataset.table` t,
UNNEST(SPLIT(REGEXP_REPLACE(TO_JSON_STRING(t), '[{}"]', ''))) kv
WHERE SPLIT(kv,':')[OFFSET(0)] NOT IN ('id', 'Country_Region')

Вы можете проверить, поиграть с выше, используя фиктивные данные, как в упрощенном примере ниже

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 1 AS id, 'China' AS Country_Region, 12 AS _1_22_20, 34 AS _1_23_20, 54 AS _1_24_20 UNION ALL
  SELECT 2 AS id, 'Italy' AS Country_Region, 22 AS _1_22_20, 44 AS _1_23_20, 64 AS _1_24_20 
)
SELECT id, Country_Region, 
  STRUCT(
      SPLIT(kv,':')[OFFSET(0)] AS ColumnName, 
      SPLIT(kv,':')[OFFSET(1)] AS Value
  ) AS `Date`
FROM `project.dataset.table` t,
UNNEST(SPLIT(REGEXP_REPLACE(TO_JSON_STRING(t), '[{}"]', ''))) kv
WHERE SPLIT(kv,':')[OFFSET(0)] NOT IN ('id', 'Country_Region')

с выводом

Row id  Country_Region  Date.ColumnName Date.Value   
1   1   China           _1_22_20        12   
2   1   China           _1_23_20        34   
3   1   China           _1_24_20        54   
4   2   Italy           _1_22_20        22   
5   2   Italy           _1_23_20        44   
6   2   Italy           _1_24_20        64   
1 голос
/ 13 апреля 2020

Вам нужно перечислить столбцы явно. Но вам не нужен CTE:

SELECT rg.Country_Region, el.timestamp, el.timestamp_value
FROM `username.bq_timeseries_covid19.recovered_global` rg CROSS JOIN
     UNNEST([STRUCT<timestamp STRING, timestamp_value INT64>
             ('2020-2-22', _2_22_20),
             ('2020-2-23', _2_23_20)
            ]) el
WHERE rg.Country_Region = 'China' and
      rg.Province_State = 'Zhejiang';

На самом деле, есть некоторые приемы, использующие JSON и манипуляции со строками, но они довольно хакерские и не стоят затраченных усилий (на мой взгляд).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...