Объединить строки в BigQuery, игнорируя нули

У меня есть таблица Google BigQuery, которая выглядит так:

║ id ║   col_1    ║  col_2  ║ updated ║

║  1 ║ first_data ║ null    ║ 4/22    ║

║  1 ║ null       ║ old     ║ 4/23    ║

║  1 ║ null       ║ correct ║ 4/24    ║

Я хотел бы создать запрос, который объединяет эти строки и «перезаписывает» пустые столбцы, если есть строка с тем же идентификатором, но столбец не равен нулю. По сути, результат должен выглядеть так:

║  1 ║ first_data ║ correct ║ 4/24    ║

Если возможно, я бы также хотел, чтобы результат представлял историю:

║  1 ║ first_data ║ old     ║ 4/23    ║

║  1 ║ first_data ║ correct ║ 4/24    ║

Но это второстепенно и не обязательно.

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
0
1 589
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Как это работает?

select a.id, max(c.col_1)col_1, a.col_2,  a.updated  from yourtable a 
 left join (
    select id, col_1, max(updated) updated from yourtable
    where col_1 is not null
    group by id, col_1)b
on a.id=b.id and a.updated=b.updated
left join  yourtable c on a.id=c.id and a.updated<>c.updated
where a.col_2 is not null and c.col_1 is not null
group by a.id,   a.col_2,  a.updated 
order by updated  
Ответ принят как подходящий

Ниже приведен стандартный SQL BigQuery.

#standardSQL
SELECT id, 
  IFNULL(col_1, FIRST_VALUE(col_1 IGNORE NULLS) OVER(win)) col_1, 
  IFNULL(col_2, FIRST_VALUE(col_2 IGNORE NULLS) OVER(win)) col_2, 
  updated
FROM `project.dataset.your_table`
WINDOW win AS (PARTITION BY id ORDER BY updated DESC 
               ROWS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING)
-- ORDER BY id, updated

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

#standardSQL
WITH `project.dataset.your_table` AS (
  SELECT 1 id, 'first_data' col_1, NULL col_2,  '4/22' updated UNION ALL
  SELECT 1,     NULL,             'old',        '4/23'         UNION ALL
  SELECT 1,     NULL,             'correct',    '4/24'         UNION ALL
  SELECT 1,    'next_data',       NULL,         '4/25'         UNION ALL
  SELECT 1,     NULL,             NULL,         '4/26'         
)
SELECT id, 
  IFNULL(col_1, FIRST_VALUE(col_1 IGNORE NULLS) OVER(win)) col_1, 
  IFNULL(col_2, FIRST_VALUE(col_2 IGNORE NULLS) OVER(win)) col_2, 
  updated
FROM `project.dataset.your_table`
WINDOW win AS (PARTITION BY id ORDER BY updated DESC 
               ROWS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING)
ORDER BY id, updated

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

Row id  col_1       col_2   updated  
1   1   first_data  null    4/22     
2   1   first_data  old     4/23     
3   1   first_data  correct 4/24     
4   1   next_data   correct 4/25     
5   1   next_data   correct 4/26     

Могу я спросить, как это адаптировать, чтобы история не записывалась, например только строка 5 в приведенном выше примере?

MarkeD 27.11.2018 15:01

В итоге я добавил ROW_NUMBER() OVER (PARTITION BY id) as n, а затем отфильтровал WHERE n=1

MarkeD 27.11.2018 15:28

@MarkeD - ROW_NUMBER () - это довольно много памяти! в большинстве случаев может закончиться ошибкой превышения ресурсов. если вы можете опубликовать свой вопрос - я предложу альтернативное решение (очевидно, формат комментариев не позволяет это сделать)

Mikhail Berlyant 27.11.2018 16:59

Ок круто спасибо выложил сюда stackoverflow.com/questions/53508405/…

MarkeD 27.11.2018 22:27

Другие вопросы по теме