【问题标题】:Deleting duplicates rows from redshift从红移中删除重复的行
【发布时间】:2016-10-01 14:58:59
【问题描述】:

我正在尝试删除我的 redshift 表中的一些重复数据。

以下是我的查询:-

With duplicates
As
(Select *, ROW_NUMBER() Over (PARTITION by record_indicator Order by record_indicator) as Duplicate From table_name)
delete from duplicates
Where Duplicate > 1 ;

这个查询给了我一个错误。

亚马逊无效操作:“删除”处或附近出现语法错误;

不确定问题是什么,因为 with 子句的语法似乎是正确的。 以前有人遇到过这种情况吗?

【问题讨论】:

    标签: sql amazon-redshift sql-delete


    【解决方案1】:
    • 此方法将保留original_table 的权限和表定义。
    • 投票最多的答案不保留对表的权限或表的原始定义。
    • 在现实世界的生产环境中,您应该采用这种方法,因为这是在生产环境中执行的最安全、最简单的方法。
    1. 创建具有唯一行的表
    CREATE TABLE unique_table as
    (
       SELECT DISTINCT * FROM original_table
    )
    ;
    
    1. 备份original_table
    CREATE TABLE backup_table as
    (
       SELECT * FROM original_table
    )
    ; 
    
    1. 截断original_table
    TRUNCATE original_table
    
    1. 将记录从unique_table 插入original_table
    INSERT INTO original_table
    (
    SELECT * FROM unique_table
    )
    ;
    

    【讨论】:

      【解决方案2】:

      如果您要处理大量数据,重新创建整个表并不总是可行或明智的。查找、删除这些行可能更容易:

      -- First identify all the rows that are duplicate
      CREATE TEMP TABLE duplicate_saleids AS
      SELECT saleid
      FROM sales
      WHERE saledateid BETWEEN 2224 AND 2231
      GROUP BY saleid
      HAVING COUNT(*) > 1;
      
      -- Extract one copy of all the duplicate rows
      CREATE TEMP TABLE new_sales(LIKE sales);
      
      INSERT INTO new_sales
      SELECT DISTINCT *
      FROM sales
      WHERE saledateid BETWEEN 2224 AND 2231
      AND saleid IN(
           SELECT saleid
           FROM duplicate_saleids
      );
      
      -- Remove all rows that were duplicated (all copies).
      DELETE FROM sales
      WHERE saledateid BETWEEN 2224 AND 2231
      AND saleid IN(
           SELECT saleid
           FROM duplicate_saleids
      );
      
      -- Insert back in the single copies
      INSERT INTO sales
      SELECT *
      FROM new_sales;
      
      -- Cleanup
      DROP TABLE duplicate_saleids;
      DROP TABLE new_sales;
      
      COMMIT;
      

      全文:https://elliot.land/post/removing-duplicate-data-in-redshift

      【讨论】:

        【解决方案3】:

        这个问题的简单回答:

        1. 首先从主表创建一个临时表,其值为row_number=1
        2. 其次,delete 主表中存在重复的所有行。
        3. 然后将临时表的值插入到主表中。

        查询:

        1. 临时表

          select id,date into #temp_a from (select *
          from (select a.*, row_number() over(partition by id order by etl_createdon desc) as rn from table a where a.id between 59 and 75 and a.date = '2018-05-24') where rn =1)a

        2. 从主表中删除所有行。

          delete from table a where a.id between 59 and 75 and a.date = '2018-05-24'

        3. 将临时表中的所有值插入主表

          insert into table a select * from #temp_a.

        【讨论】:

          【解决方案4】:

          Redshift 就是这样(对任何列都没有强制唯一性),Ziggy 的第三个选项可能是最好的。一旦我们决定采用临时表路线,将所有东西全部换掉会更有效。在 Redshift 中删除和插入的开销很大。

          begin;
          create table table_name_new as select distinct * from table_name;
          alter table table_name rename to table_name_old;
          alter table table_name_new rename to table_name;
          drop table table_name_old;
          commit;
          

          如果空间不是问题,您可以将旧表保留一段时间,然后使用此处描述的其他方法来验证原始会计中的行数是否与新表中的行数匹配。

          如果您正在对此类表进行持续加载,您将希望在此过程中暂停该过程。

          如果重复的数量只是大表的一小部分,您可能想尝试将重复的不同记录复制到临时表,然后从原始表中删除与临时表连接的所有记录。然后append将临时表恢复到原来的状态。确保你 vacuum 之后的原始表(无论如何,你应该按计划为大型表执行此操作)。

          【讨论】:

            【解决方案5】:

            以下删除'tablename'中所有有重复的记录,不会对表进行去重:

            DELETE FROM tablename
            WHERE id IN (
                SELECT id
                FROM (
                      SELECT id,
                      ROW_NUMBER() OVER (partition BY column1, column2, column3 ORDER BY id) AS rnum
                      FROM tablename
                     ) t
                 WHERE t.rnum > 1);
            

            Postgres administrative snippets

            【讨论】:

            • 只有在 ID 重复的情况下才会生效 - 在这种情况下,行号函数会区分 ID。
            • 这将删除“所有”副本示例sqlfiddle.com/#!15/043b4/2 但我认为最初的问题是关于如何删除所有重复项并仅保留唯一行的一份副本。
            • 是的,这不是问题中问题的解决方案。我打了自己的脸发布它。感谢您发布 sqlfiddle 链接。
            • 我删除它好吗?我不希望任何人被误导。
            • 我认为只需更新它会删除所有副本的答案,这样人们就会知道它实际上做了什么。
            【解决方案6】:

            您的查询不起作用,因为 Redshift 不允许在 WITH 子句之后使用 DELETE。只允许SELECTUPDATE 以及其他几个(见WITH clause

            解决方案(在我的情况下):

            我的表 events 上确实有一个 id 列,其中包含重复的行并唯一标识记录。此列id 与您的record_indicator 相同。

            很遗憾,我无法创建临时表,因为我在使用 SELECT DISTINCT 时遇到了以下错误:

            ERROR: Intermediate result row exceeds database block size

            但这就像一个魅力:

            CREATE TABLE temp as (
                SELECT *,ROW_NUMBER() OVER (PARTITION BY id ORDER BY id) AS rownumber 
                FROM events
            );
            

            导致temp 表:

            id | rownumber | ...
            ----------------
            1  | 1         | ...
            1  | 2         | ...
            2  | 1         | ...
            2  | 2         | ...
            

            现在可以通过删除 rownumber 大于 1 的行来删除重复项:

            DELETE FROM temp WHERE rownumber > 1
            

            然后重命名表格并完成。

            【讨论】:

              【解决方案7】:

              这应该行得通。你可以做的替代方案:

              With 
                duplicates As (
                  Select *, ROW_NUMBER() Over (PARTITION by record_indicator
                                               Order by record_indicator) as Duplicate
                  From table_name)
              delete from table_name
              where id in (select id from duplicates Where Duplicate > 1);
              

              delete from table_name
              where id in (
                select id
                from (
                  Select id, ROW_NUMBER() Over (PARTITION by record_indicator
                                               Order by record_indicator) as Duplicate
                  From table_name) x
                Where Duplicate > 1);
              

              如果您没有主键,您可以执行以下操作:

              BEGIN;
              CREATE TEMP TABLE mydups ON COMMIT DROP AS
                SELECT DISTINCT ON (record_indicator) *
                FROM table_name
                ORDER BY record_indicator --, other_optional_priority_field DESC
              ;
              
              DELETE FROM table_name
              WHERE record_indicator IN (
                SELECT record_indicator FROM mydups);
              
              INSERT INTO table_name SELECT * FROM mydups;
              COMMIT;
              

              【讨论】:

              • 是的,不知道为什么它不起作用。我尝试了您的第一个查询并收到相同的错误。在第二个查询中,“id”应该是主键吗?
              • 我的主键是record_indicator。由于 Redshift 不强制执行唯一主键,因此它也是重复的
              • @Neil 刚刚用没有 PK / 重复 ID 的情况扩展了答案。
              • 如上所述,我的第一个选项错误,第二个危险地删除了重复行的所有副本,而不是留下一个。对于选项 3,我得到“错误:不支持 SELECT DISTINCT ON”。
              • 最后一个没有主键的解决方案在redshift上不起作用,看起来像postgres 9.x
              猜你喜欢
              • 2012-10-21
              • 2017-10-11
              • 1970-01-01
              • 2016-08-20
              • 1970-01-01
              • 1970-01-01
              • 2010-11-05
              • 2018-03-01
              相关资源
              最近更新 更多