我有一个具有以下架构的产品表:
id createdOn, updatedOn, stock, status
createdOn
和updatedOn
是TimeStamp
。
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
)
但是,这行不通...我没有自动递增字段来区分行。
我该如何解决?
答案 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
无论如何,不确定其优化程度如何...