从BigQuery表中删除重复的行

The*_*oat 29 distinct google-bigquery

我有一个包含> 1M行数据和20多列的表.

在我的表格(tableX)中,我在一个特定列(troubleColumn)中识别出重复记录(~80k).

如果可能的话,我想保留原始表名并从我有问题的列中删除重复记录,否则我可以创建一个具有相同模式但没有重复项的新表(tableXfinal).

我不擅长SQL或任何其他编程语言,所以请原谅我的无知.

delete from Accidents.CleanedFilledCombined 
where Fixed_Accident_Index 
in(select Fixed_Accident_Index from Accidents.CleanedFilledCombined 
group by Fixed_Accident_Index 
having count(Fixed_Accident_Index) >1);
Run Code Online (Sandbox Code Playgroud)

Jor*_*ani 39

您可以通过运行重写表的查询来删除重复项(您可以使用与目标相同的表,也可以创建新表,验证它是否具有您想要的内容,然后将其复制到旧表上).

应该工作的查询在这里:

SELECT *
FROM (
  SELECT
      *,
      ROW_NUMBER()
          OVER (PARTITION BY Fixed_Accident_Index)
          row_number
  FROM Accidents.CleanedFilledCombined
)
WHERE row_number = 1
Run Code Online (Sandbox Code Playgroud)

  • 请参阅下面的答案,以获取#standardSQL更具扩展性的替代方案 (2认同)
  • 有没有办法通过 API 做到这一点? (2认同)
  • 覆盖的一个问题是新表的模式字段都是可以为空的 (2认同)
  • 一般来说,覆盖现有表是不好的做法,因为您可能会发现您在查询中的某个地方犯了错误。最好把它写成一个单独的表,一旦你确定它是好的,删除旧的并重命名新的。 (2认同)

Fel*_*ffa 24

替代乔丹的答案 - 当副本太多时,这个答案会更好:

#standardSQL
SELECT event.* FROM (
  SELECT ARRAY_AGG(
    t ORDER BY t.created_at DESC LIMIT 1
  )[OFFSET(0)]  event
  FROM `githubarchive.month.201706` t 
  # GROUP BY the id you are de-duplicating by
  GROUP BY actor.id
)
Run Code Online (Sandbox Code Playgroud)

或者更短的版本(占用任何行,而不是最新行):

SELECT k.*
FROM (
  SELECT ARRAY_AGG(x LIMIT 1)[OFFSET(0)] k 
  FROM `fh-bigquery.reddit_comments.2017_01` x 
  GROUP BY id
)
Run Code Online (Sandbox Code Playgroud)

要对现有表上的行进行重复数据删除:

CREATE OR REPLACE TABLE `deleting.deduplicating_table`
AS
# SELECT id FROM UNNEST([1,1,1,2,2]) id
SELECT k.*
FROM (
  SELECT ARRAY_AGG(row LIMIT 1)[OFFSET(0)] k 
  FROM `deleting.deduplicating_table` row
  GROUP BY id
)
Run Code Online (Sandbox Code Playgroud)


Sem*_*mra 9

不知道为什么没人提到DISTINCT查询。

这是清除重复行的方法:

CREATE OR REPLACE TABLE project.dataset.table
AS
SELECT DISTINCT * FROM project.dataset.table
Run Code Online (Sandbox Code Playgroud)

  • 如果现有表已分区,则此方法不起作用。 (4认同)
  • 或者如果我们想要对其他列中具有相同 id 但不同值的行进行重复数据删除,即 Updated_at (4认同)
  • 绝对是做我想做的事情的最简单的方法 - 谢谢!不直接回答OP的问题,但它回答了我为什么来到这里:) @OriolNieto - 它适用于你的所有专栏。如果您想验证它的工作原理,可以将 * 替换为特定列的列表 (2认同)
  • 我认为如果你有一个结构列,它就不能与 * 一起使用。这可能就是@OriolNieto 所看到的。 (2认同)

Mik*_*ant 6

如果您的架构没有任何记录 - 以下variationJordan 的答案将适用于在同一张表或新表上书写等。

SELECT <list of original fields>
FROM (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY Fixed_Accident_Index) AS pos,
  FROM Accidents.CleanedFilledCombined
)
WHERE pos = 1
Run Code Online (Sandbox Code Playgroud)

在更通用的情况下 - 具有记录/网络字段等的复杂模式 - 上述方法可能是一个挑战。

我建议尝试使用Tabledata: insertAll API,其中rows[].insertId设置为每行各自的 Fixed_Accident_Index。在这种情况下,BigQuery 将消除重复行

当然,这将涉及一些客户端编码 - 所以可能与这个特定问题无关。我自己也没有尝试过这种方法,但觉得尝试一下可能很有趣:o)