如何在BigQuery中按时间戳删除重复的行?

时间:2018-09-16 08:52:20

标签: sql google-bigquery

我有一个具有以下架构的产品表:

id  createdOn, updatedOn, stock, status

createdOnupdatedOnTimeStamp

createdOn是paratition字段。

说这是我现在拥有的数据:

id  createdOn,                    updatedOn,                stock, status
1   2018-09-14 14:14:24.305676   2018-09-14 14:14:24.305676  10    5
2   2018-09-14 14:14:24.305676   2018-09-14 14:14:24.305676  5     12
3   2018-09-14 14:14:24.305676   2018-09-14 14:14:24.305676  10     5

我有一个ETL,它向该表追加了新行。当ETL完成时,我可能会遇到同一id具有多于1行的情况。

例如:

id  createdOn,                    updatedOn,                stock, status
1   2018-09-14 14:14:24.305676   2018-09-14 14:14:24.305676  10    5
2   2018-09-14 14:14:24.305676   2018-09-14 14:14:24.305676  5     12
3   2018-09-14 14:14:24.305676   2018-09-14 14:14:24.305676  10     5
1   2018-09-14 14:14:24.305676   2018-09-14 14:14:24.305676  10     5
3   2018-09-14 14:14:24.305676   2018-09-15 10:00:00.000000  7     5

我想要一个查询,该查询将在表上运行,并确保每个id只有1行-应保留带有MAX(updatedOn)的行。每个id的MAX(updatedOn)最多可以有1行-在这种情况下,可以保证它们是相同的,因为如果不相同,则updatedOn字段将被修改。

查询后,表将如下所示:

id  createdOn,                    updatedOn,                stock, status
2   2018-09-14 14:14:24.305676   2018-09-14 14:14:24.305676  5     12
1   2018-09-14 14:14:24.305676   2018-09-14 14:14:24.305676  10     5
3   2018-09-14 14:14:24.305676   2018-09-15 10:00:00.000000  7     5

如何编写有效执行此操作的查询?

我知道应该是这样的:

DELETE FROM products
WHERE id NOT IN
(
    SELECT MAX(id)
    FROM products
    GROUP BY id
)

但是,这行不通...我没有自动递增字段来区分行。

我该如何解决?

3 个答案:

答案 0 :(得分:3)

使用row_number函数

DELETE FROM products
WHERE STRUCT(id,createdOn,stock) IN (
        select id,createdOn,stock from
        (SELECT id,createdOn,stock,
          ROW_NUMBER()
                  OVER (PARTITION BY createdOn,stock,updatedOn order by id) as rn from products
                  ) t where rn>1
         ) 

您可以遵循的另一种方法,而不是删除,可以替换表

CREATE OR REPLACE TABLE products AS
SELECT * EXCEPT(rn)
FROM (
  SELECT *, ROW_NUMBER() OVER(PARTITION BY createdOn,stock,updatedOn order by id) rn
  FROM products
) 
WHERE rn> 1 

答案 1 :(得分:1)

我强烈建议您仅创建一个新表:

create table correct_table as
    select distinct id, createdOn, updatedOn
    from etl_table;

BigQuery的优势在于处理数据。当需要更新或删除内容时,我会尝试寻找其他解决方案(例如复制表)。

您可能想重新考虑您的处理。只是让ETL用新行加载表。然后使用BigQuery插入尚不存在的新行。换句话说,插入行然后删除它们不是行之有效的方法。

答案 2 :(得分:0)

我认为Gordon Linoff是正确的,BigQuery用例不是一直在操纵数据和更新已经存在的行。 It's to fill it enormously and then analyze that data

无论如何,此查询将仅返回您需要的行:

SELECT DISTINCT id, createdOn,  updatedOn,  stock,  status
FROM `project.dataset.maxtimestamp` AS t1
INNER JOIN (SELECT id AS i2, MAX(updatedOn) AS up
FROM `project.dataset.maxtimestamp`
GROUP BY id) AS t2
ON t1.id = t2.i2 AND t1.updatedOn = t2.up

以及您已经找到的这个

SELECT id,  createdOn,  updatedOn,  stock,  status
FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY createdOn, id ORDER BY updatedOn desc) AS rn
       FROM `training-wave-12-vmarin.asdf.duplicated_timestamp` AS t2)
WHERE rn>1

无论如何,不​​确定其优化程度如何...