Использование модели добавления для частичного обновления строк в BigQuery - PullRequest
1 голос
/ 12 апреля 2019

Предположим, у меня есть следующая запись в BQ:

id        name           age    timestamp
1         "tom"          20     2019-01-01

Затем я выполняю два "обновления" этой записи, используя потоковый API для "добавления" дополнительных данных - https://cloud.google.com/bigquery/streaming-data-into-bigquery.Это главным образом для того, чтобы обойти квоту обновлений, которую обеспечивает BQ (и это приложение с высокой степенью записи).

Затем я добавляю два изменения в таблицу, одно обновление, которое просто изменяет name,а затем одно обновление, которое просто изменяет age.Вот три записи после обновлений:

id        name           age    timestamp
1         "tom"          20     2019-01-01
1         "Tom"          null   2019-02-01
1         null           21     2019-03-03

Затем я хочу запросить эту запись, чтобы получить наиболее актуальную информацию.Вот как я начал:

SELECT id, **name**, **age**,max(timestamp)
FROM table
GROUP BY id 
-- 1,"Tom",21,2019-03-03

Как я могу получить правильное имя и возраст здесь?Обратите внимание, что в записи могут быть тысячи обновлений, поэтому я не хочу писать 1000 операторов case, если это вообще возможно.

По различным другим причинам у меня обычно не будет всей строкиданные за один раз, у меня будет только RowID + FieldName + FieldValue.

Я предполагаю, что план B здесь состоит в том, чтобы выполнить запрос для получения текущих данных, а затем добавить свои изменения, чтобы вставить новую строку, но яЯ надеюсь, что есть способ сделать это за один раз без необходимости делать два запроса.

Ответы [ 2 ]

4 голосов
/ 12 апреля 2019

Ниже для BigQuery Standard SQL

#standardSQL
SELECT id, 
  ARRAY_AGG(name IGNORE NULLS ORDER BY ts DESC LIMIT 1)[OFFSET(0)] name,
  ARRAY_AGG(age IGNORE NULLS ORDER BY ts DESC LIMIT 1)[OFFSET(0)] age,
  MAX(ts) ts  
FROM `project.dataset.table`
GROUP BY id   

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

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 1 id, "tom" name, 20 age, DATE '2019-01-01' ts UNION ALL
  SELECT 1, "Tom", NULL, '2019-02-01' UNION ALL
  SELECT 1, NULL, 21, '2019-03-03' 
)
SELECT id, 
  ARRAY_AGG(name IGNORE NULLS ORDER BY ts DESC LIMIT 1)[OFFSET(0)] name,
  ARRAY_AGG(age IGNORE NULLS ORDER BY ts DESC LIMIT 1)[OFFSET(0)] age,
  MAX(ts) ts  
FROM `project.dataset.table`
GROUP BY id   

с результатом

Row id  name    age ts   
1   1   Tom 21  2019-03-03  
0 голосов
/ 12 апреля 2019

Это классический случай применения аналитических функций в стандартном SQL.

Вот как вы можете достичь своих результатов:

select id, name, age from (
  select id, name, age, ts, rank() over (partition by id order by ts desc) rnk
  from `yourdataset.yourtable`
)
where rnk = 1

Это подгруппирует ваши записи на основе id и выберите запись с самым последним ts (с указанием записи, последней добавленной для данного id).

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