2017-01-26 2 views
0

У меня есть недельный процесс, который выполняет полную операцию замены на нескольких таблицах. Этот процесс является еженедельным, поскольку в целом имеется большое количество данных. Тем не менее, мы также хотим делать ежедневные/ежечасные дельта-обновления, поэтому система будет больше синхронизироваться с производством.Устранение таблицы при сохранении структур записи

Когда мы обновляем данные, мы создаем дубликаты строк (обновления существующей строки), от которых я хочу избавиться. Для достижения этой цели, я написал сценарий питона, который запускает следующий запрос на таблицу, вставив результаты обратно в него:

QUERY = """#standardSQL 
      select {fields} 
      from (
       select * 
       , max(record_insert_time) over (partition by id) as max_record_insert_time 
       from {client_name}_{environment}.{table} as a 
      ) 
      where 1=1 
      and record_insert_time = max_record_insert_time""" 

Переменная {fields} заменяется списком всех столбцов таблицы; Я не могу использовать *, потому что это будет работать только для 1-го запуска (следующее будет уже иметь поле под названием max_record_insert_time, и это вызовет проблему двусмысленности).

Все работает должным образом, за одним исключением - некоторые из столбцов в таблице: RECORD Тип данных; несмотря на то, что они не используют для них псевдонимы и выбирают их полное имя (например, record_name.child_name), когда вывод записывается обратно в таблицу, результаты сглаживаются. Я добавил конфигурацию flattenResults: False в свой код, но это не изменило результат.

Мне бы хотелось услышать мысли о том, как решить эту проблему, используя мой существующий план, другие методы дедупликации или другие методы обработки дельта-обновлений в целом.

ответ

2

Может быть, вы можете использовать в наружном заявлении

SELECT * EXCEPT (max_record_insert_time)

Это должно держать точную структуру записи. (Для получения более подробной документации см https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select-except)

Альтернативный подход, будет включать в {fields} колонках только на высшем уровне, даже если они не являются листья, т.е. просто record_name и не record_name.*

+0

Holy moly! Это уникальная функция BQ? Никогда не встречал этот синтаксис раньше! Также не смотрите в документации. –

+2

Вы можете прочитать об этом ['Синтаксис запроса] (https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select-except). –

0

Ниже ответ, безусловно, не лучше, чем использование просто SELECT * EXCEPT модификатора, но хотел представить альтернативную версию

SELECT t.* 
FROM (
    SELECT 
    id, MAX(record_insert_time) AS max_record_insert_time, 
    ARRAY_AGG(t) AS all_records_for_id 
    FROM yourTable AS t GROUP BY id 
), UNNEST(all_records_for_id) AS t 
WHERE t.record_insert_time = max_record_insert_time 
ORDER BY id 

Что выше запрос делает это - первые группы все записи оптоволоконной r каждый id в array of respective rows вместе с max value for insert_time. Затем для каждого id - он просто выравнивает все (ранее агрегированные) строки и выбирает только строки с максимальным временем вставки insert_time. Результат такой же, как ожидалось. Нет Analytic Function, но довольно простой Aggregation. Но дополнительное использование UNNEST ... По-прежнему - по крайней мере, различный вариант: o)

+0

Это интересный подход. Небольшое пояснение - из моего опыта работы с BigQuery, когда один псевдоним таблицы и выполняет выбор с использованием псевдонима таблицы без второго псевдонима, чтобы переименовать выбранный столбец (например, 't.field' vs' t.field как field'), вывод всегда будет указывать 't_' каждому имени поля. Однако мой опыт в основном ограничивается устаревшим SQL, поэтому, возможно, в стандартном SQL это происходит по-разному. Не будет ли это так? –

+1

это правильно для устаревшего sql.но в стандартном sql t_ не добавляется. так что вы получите точно оригинальную структуру/именование –

 Смежные вопросы

  • Нет связанных вопросов^_^