Sql 如何在BigQuery中按时间戳删除重复的行?
我有一个具有以下架构的products表:Sql 如何在BigQuery中按时间戳删除重复的行?,sql,google-bigquery,Sql,Google Bigquery,我有一个具有以下架构的products表: id createdOn, updatedOn, stock, status createdOn和updatedOn是时间戳 createdOn是分隔字段 假设这是我现在掌握的数据: id createdOn, updatedOn, stock, status 1 2018-09-14 14:14:24.305676 2018-09-14 14:14:24.305676
id createdOn, updatedOn, stock, status
createdOn
和updatedOn
是时间戳
createdOn
是分隔字段
假设这是我现在掌握的数据:
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
有多行的情况
例如:
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只有一行-带有MAX(updatedOn)
的行应该保留。每个id的MAX(updatedOn)
可以有多行-在这种情况下,可以保证它们是相同的,因为如果它们不是相同的,那么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
)
然而,这是行不通的。。。我没有自动递增字段来区分行
如何解决此问题?使用
行数
函数
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
使用
行号
功能
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
我强烈建议您只创建一个新表:
create table correct_table as
select distinct id, createdOn, updatedOn
from etl_table;
BigQuery的优势在于处理数据。当需要更新或删除时,我尝试寻找其他解决方案(例如复制表)
您可能需要重新思考您的处理过程。只需让ETL加载一个包含新行的表。然后使用BigQuery插入不存在的新行。换句话说,插入行然后删除它们不是一种方法。我强烈建议您只创建一个新表:
create table correct_table as
select distinct id, createdOn, updatedOn
from etl_table;
BigQuery的优势在于处理数据。当需要更新或删除时,我尝试寻找其他解决方案(例如复制表)
您可能需要重新思考您的处理过程。只需让ETL加载一个包含新行的表。然后使用BigQuery插入不存在的新行。换句话说,插入行然后删除它们不是一种方法。我认为Gordon Linoff是对的,BigQuery用例不是一直操作数据和更新现有行 无论如何,此查询将只返回所需的行:
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
无论如何,我不确定它有多优化…我认为Gordon Linoff是对的,BigQuery用例不是一直操作数据和更新现有行 无论如何,此查询将只返回所需的行:
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
无论如何,不确定它的优化程度…语法错误:在[6:15]处出现意外标识符“行号”@Programmer120请参见now@Pentium10为什么我需要选择*?这会带来不必要的列。。这在BigQuery中需要花钱。分区不是应该按id顺序更新吗?您建议的分区语法更好,除非您不返回任何内容,否则select*不是问题,在delete语法中没有成本问题。@Pentium10但您确实返回了。。。查询将完全执行,然后才执行删除。语法错误:在[6:15]处出现意外标识符“row_number”@Programmer120请参阅now@Pentium10为什么我需要选择*?这会带来不必要的列。。这在BigQuery中需要花钱。分区不是应该按id顺序更新吗?您建议的分区语法更好,除非您不返回任何内容,否则select*不是问题,在delete语法中没有成本问题。@Pentium10但您确实返回了。。。完全执行查询,然后才执行删除。我不知道这将如何工作。“旧表”可以包含不在我正在运行的ETL中的行。我实际上想做的是某种升级的解决方案。我可以创建一个WIP表并对其进行处理,当完成从该表到生产表的写截短操作时,仍然需要执行删除或更新。。没有保存任何内容。@Programmer120。您不需要执行
delete
s或update
s,或者至少我还不需要在我在BigQuery中实现的系统上执行这些操作。但这不是你在这里问的问题。我只是提供了一个超出问题范围的解决方案。我提供的答案是创建一个新表,而不是从旧表中删除(使用选择distinct
,但是如果您有问题中未提到的其他列,您可能需要稍微不同的逻辑)。我知道你把它带出了范围。。没关系,我只是不明白你的逻辑。您建议运行ETL,然后仅从旧表复制不存在的id。这仍然需要逐行传递。请记住,我的分区位于createdate上,但在这里不参与。我不知道这将如何工作。“旧表”可以包含不在我正在运行的ETL中的行。我实际上想做的是某种升级的解决方案。我可以创建一个WIP表并对其进行处理,当完成从该表到生产表的写截短操作时,仍然需要执行删除或更新。。没有保存任何内容。@Programmer120。您不需要执行delete
s或update
s,或者至少我还不需要在我在BigQuery中实现的系统上执行这些操作。但这不是你在这里问的问题。我只是提供了一个超出问题范围的解决方案。我提供的答案是创建一个新表,而不是从旧表中删除(使用选择distinct
),但如果您有问题中未提到的其他列,则可能需要sl