在保留记录结构的同时对表进行重复计算

时间:2017-01-26 15:09:21

标签: python google-bigquery

我有一个每周进程,可以对几张表进行完全替换操作。该过程是每周一次,因为整体上有大量数据。但是,我们还希望每天/每小时增量更新,因此系统将更加与生产同步。

当我们更新数据时,我们正在创建行的重复(现有行的更新),我想摆脱它。为此,我编写了一个python脚本,在一个表上运行以下查询,将结果插入其中:

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 个答案:

答案 0 :(得分: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.*

答案 1 :(得分: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 

以上查询的作用是 - 首先将每个id的所有记录分组到array of respective rows以及max value for insert_time。然后,对于每个id - 它只是展平所有(先前聚合的)行,并仅选择insert_time匹配最大时间的行。结果如预期。没有Analytic Function涉及但相当简单Aggregation。但额外使用UNNEST ...... 仍然 - 至少有不同的选择:o)