如何删除重复的行?

时间:2008-08-20 21:51:30

标签: sql-server tsql duplicates

从相当大的 SQL Server 表(即300,000多行)中删除重复行的最佳方法是什么?

由于存在RowID标识字段,行当然不会是完美的重复。

MyTable的

RowID int not null identity(1,1) primary key,
Col1 varchar(20) not null,
Col2 varchar(2048) not null,
Col3 tinyint not null

40 个答案:

答案 0 :(得分:1102)

假设没有空,则GROUP BY列为唯一列,SELECT MIN (or MAX) RowId为要保留的行。然后,只删除没有行id的所有内容:

DELETE FROM MyTable
LEFT OUTER JOIN (
   SELECT MIN(RowId) as RowId, Col1, Col2, Col3 
   FROM MyTable 
   GROUP BY Col1, Col2, Col3
) as KeepRows ON
   MyTable.RowId = KeepRows.RowId
WHERE
   KeepRows.RowId IS NULL

如果您有GUID而不是整数,则可以替换

MIN(RowId)

CONVERT(uniqueidentifier, MIN(CONVERT(char(36), MyGuidColumn)))

答案 1 :(得分:731)

另一种可能的方法是

; 

--Ensure that any immediately preceding statement is terminated with a semicolon above
WITH cte
     AS (SELECT ROW_NUMBER() OVER (PARTITION BY Col1, Col2, Col3 
                                       ORDER BY ( SELECT 0)) RN
         FROM   #MyTable)
DELETE FROM cte
WHERE  RN > 1;

我正在使用上面的ORDER BY (SELECT 0)因为它是任意哪一行在出现平局时保留。

例如,要保留RowID订单中的最新版本,您可以使用ORDER BY RowID DESC

执行计划

此处的执行计划通常比接受的答案更简单,更有效,因为它不需要自我加入。

Execution Plans

但情况并非总是如此。可能首选GROUP BY解决方案的地方是优先选择hash aggregate而不是流聚合的情况。

ROW_NUMBER解决方案总是提供相同的计划,而GROUP BY策略更灵活。

Execution Plans

可能有利于哈希聚合方法的因素是

  • 分区列上没有有用的索引
  • 每组中重复次数相对较少的群体相对较少

在第二种情况的极端版本​​中(如果每个组中有很多重复的组很少),也可以考虑简单地插入行以保存到新表中,然后TRUNCATE - 将原始文件复制并复制它们与删除非常高比例的行相比,最小化日志记录。

答案 2 :(得分:141)

Microsoft支持网站上的removing duplicates上有一篇很好的文章。这是非常保守的 - 他们让你在不同的步骤中做所有事情 - 但它应该适用于大型表。

我过去曾经使用过自联接来做这件事,虽然它可能会被一个HAVING子句搞定:

DELETE dupes
FROM MyTable dupes, MyTable fullTable
WHERE dupes.dupField = fullTable.dupField 
AND dupes.secondDupField = fullTable.secondDupField 
AND dupes.uniqueField > fullTable.uniqueField

答案 3 :(得分:91)

以下查询对删除重复行很有用。此示例中的表格以ID作为标识列,而具有重复数据的列为Column1Column2Column3

DELETE FROM TableName
WHERE  ID NOT IN (SELECT MAX(ID)
                  FROM   TableName
                  GROUP  BY Column1,
                            Column2,
                            Column3
                  /*Even if ID is not null-able SQL Server treats MAX(ID) as potentially
                    nullable. Because of semantics of NOT IN (NULL) including the clause
                    below can simplify the plan*/
                  HAVING MAX(ID) IS NOT NULL) 

以下脚本显示了GROUP BYHAVINGORDER BY在一个查询中的用法,并返回带有重复列及其计数的结果。

SELECT YourColumnName,
       COUNT(*) TotalCount
FROM   YourTableName
GROUP  BY YourColumnName
HAVING COUNT(*) > 1
ORDER  BY COUNT(*) DESC 

答案 4 :(得分:58)

delete t1
from table t1, table t2
where t1.columnA = t2.columnA
and t1.rowid>t2.rowid

Postgres:

delete
from table t1
using table t2
where t1.columnA = t2.columnA
and t1.rowid > t2.rowid

答案 5 :(得分:42)

DELETE LU 
FROM   (SELECT *, 
               Row_number() 
                 OVER ( 
                   partition BY col1, col1, col3 
                   ORDER BY rowid DESC) [Row] 
        FROM   mytable) LU 
WHERE  [row] > 1 

答案 6 :(得分:38)

这将删除重复的行,但第一行除外

DELETE
FROM
    Mytable
WHERE
    RowID NOT IN (
        SELECT
            MIN(RowID)
        FROM
            Mytable
        GROUP BY
            Col1,
            Col2,
            Col3
    )

参考(http://www.codeproject.com/Articles/157977/Remove-Duplicate-Rows-from-a-Table-in-SQL-Server

答案 7 :(得分:29)

我更喜欢CTE从sql server table中删除重复的行

强烈建议您遵循以下文章:: http://codaffection.com/sql-server-article/delete-duplicate-rows-in-sql-server/

  

保持原创

WITH CTE AS
(
SELECT *,ROW_NUMBER() OVER (PARTITION BY col1,col2,col3 ORDER BY col1,col2,col3) AS RN
FROM MyTable
)

DELETE FROM CTE WHERE RN<>1
  

不保留原件

WITH CTE AS
(SELECT *,R=RANK() OVER (ORDER BY col1,col2,col3)
FROM MyTable)
 
DELETE CTE
WHERE R IN (SELECT R FROM CTE GROUP BY R HAVING COUNT(*)>1)

答案 8 :(得分:22)

快速和脏删除精确重复的行(对于小表):

select  distinct * into t2 from t1;
delete from t1;
insert into t1 select *  from t2;
drop table t2;

答案 9 :(得分:20)

我更喜欢带有count(*)&gt;的子查询\ 1内部联接的解决方案,因为我发现它更容易阅读,并且很容易变成SELECT语句来验证在运行之前将删除的内容。

--DELETE FROM table1 
--WHERE id IN ( 
     SELECT MIN(id) FROM table1 
     GROUP BY col1, col2, col3 
     -- could add a WHERE clause here to further filter
     HAVING count(*) > 1
--)

答案 10 :(得分:19)

获取重复行:

SELECT
name, email, COUNT(*)
FROM 
users
GROUP BY
name, email
HAVING COUNT(*) > 1

删除重复行:

DELETE users 
WHERE rowid NOT IN 
(SELECT MIN(rowid)
FROM users
GROUP BY name, email);      

答案 11 :(得分:16)

SELECT  DISTINCT *
      INTO tempdb.dbo.tmpTable
FROM myTable

TRUNCATE TABLE myTable
INSERT INTO myTable SELECT * FROM tempdb.dbo.tmpTable
DROP TABLE tempdb.dbo.tmpTable

答案 12 :(得分:14)

使用CTE。我们的想法是加入一个或多个形成重复记录的列,然后删除您喜欢的任何一个:

;with cte as (
    select 
        min(PrimaryKey) as PrimaryKey
        UniqueColumn1,
        UniqueColumn2
    from dbo.DuplicatesTable 
    group by
        UniqueColumn1, UniqueColumn1
    having count(*) > 1
)
delete d
from dbo.DuplicatesTable d 
inner join cte on 
    d.PrimaryKey > cte.PrimaryKey and
    d.UniqueColumn1 = cte.UniqueColumn1 and 
    d.UniqueColumn2 = cte.UniqueColumn2;

答案 13 :(得分:14)

我认为我会分享我的解决方案,因为它在特殊情况下有效。 我的情况是,具有重复值的表没有外键(因为这些值是从另一个数据库复制的)。

begin transaction
-- create temp table with identical structure as source table
Select * Into #temp From tableName Where 1 = 2

-- insert distinct values into temp
insert into #temp 
select distinct * 
from  tableName

-- delete from source
delete from tableName 

-- insert into source from temp
insert into tableName 
select * 
from #temp

rollback transaction
-- if this works, change rollback to commit and execute again to keep you changes!!

PS:在处理这样的事情时,我总是使用一个事务,这不仅可以确保所有内容都作为一个整体执行,而且还允许我在不冒任何风险的情况下进行测试。但是当然你还是应该备份,以确保......

答案 14 :(得分:13)

此查询对我来说表现非常好:

DELETE tbl
FROM
    MyTable tbl
WHERE
    EXISTS (
        SELECT
            *
        FROM
            MyTable tbl2
        WHERE
            tbl2.SameValue = tbl.SameValue
        AND tbl.IdUniqueValue < tbl2.IdUniqueValue
    )

它从2M(50%重复)的表中删除了超过30秒的1M行

答案 15 :(得分:13)

可以在粘贴的链接here找到另一个简单的解决方案。这个容易掌握,似乎对大多数类似的问题都有效。它适用于SQL Server,但使用的概念是可以接受的。

以下是链接页面的相关部分:

考虑这些数据:

EMPLOYEE_ID ATTENDANCE_DATE
A001    2011-01-01
A001    2011-01-01
A002    2011-01-01
A002    2011-01-01
A002    2011-01-01
A003    2011-01-01

那么我们如何删除那些重复的数据?

首先,使用以下代码在该表中插入标识列:

ALTER TABLE dbo.ATTENDANCE ADD AUTOID INT IDENTITY(1,1)  

使用以下代码解决此问题:

DELETE FROM dbo.ATTENDANCE WHERE AUTOID NOT IN (SELECT MIN(AUTOID) _
    FROM dbo.ATTENDANCE GROUP BY EMPLOYEE_ID,ATTENDANCE_DATE) 

答案 16 :(得分:12)

以下是关于removing duplicates的另一篇好文章。

它讨论了为什么它很难:“ SQL基于关系代数,并且重复在关系代数中不会发生,因为在集合中不允许重复。

临时表解决方案和两个mysql示例。

将来您是要在数据库级别,还是从应用程序的角度来阻止它。我建议数据库级别,因为您的数据库应该负责维护引用完整性,开发人员只会导致问题;)

答案 17 :(得分:12)

哦,当然。使用临时表。如果你想要一个“有效”的单一,不是非常高效的陈述,你可以选择:

DELETE FROM MyTable WHERE NOT RowID IN
    (SELECT 
        (SELECT TOP 1 RowID FROM MyTable mt2 
        WHERE mt2.Col1 = mt.Col1 
        AND mt2.Col2 = mt.Col2 
        AND mt2.Col3 = mt.Col3) 
    FROM MyTable mt)

基本上,对于表中的每一行,子选择查找与所考虑的行完全相同的所有行的顶部RowID。因此,您最终会得到一个表示“原始”非重复行的RowID列表。

答案 18 :(得分:11)

我有一张表,我需要保存不重复的行。 我不确定速度或效率。

DELETE FROM myTable WHERE RowID IN (
  SELECT MIN(RowID) AS IDNo FROM myTable
  GROUP BY Col1, Col2, Col3
  HAVING COUNT(*) = 2 )

答案 19 :(得分:10)

使用此

  private boolean shouldNotLeakConnection(com.zaxxer.hikari.HikariDataSource);
    Code:
       0: ldc           #115                // String INSERT INTO error_logs (description) values (?)
       2: astore_2      
       3: aconst_null   
       4: astore_3      
       5: aconst_null   
       6: astore        4
       8: aload_1       
       9: invokevirtual #117                // Method com/zaxxer/hikari/HikariDataSource.getConnection:()Ljava/sql/Connection;
      12: astore        5
      14: aload         5
      16: aload_2       
      17: invokeinterface #121,  2          // InterfaceMethod java/sql/Connection.prepareStatement:(Ljava/lang/String;)Ljava/sql/PreparedStatement;
      22: astore        6
      24: aload         6
      26: iconst_1      
      27: ldc           #127                // String description
      29: invokeinterface #129,  3          // InterfaceMethod java/sql/PreparedStatement.setString:(ILjava/lang/String;)V
      34: aload         6
      36: invokeinterface #135,  1          // InterfaceMethod java/sql/PreparedStatement.executeUpdate:()I
      41: ifeq          46
      44: iconst_1      
      45: ireturn       
      46: iconst_0      
      47: aload         6
      49: ifnull        59
      52: aload         6
      54: invokeinterface #139,  1          // InterfaceMethod java/sql/PreparedStatement.close:()V
      59: aload         5
      61: ifnull        71
      64: aload         5
      66: invokeinterface #142,  1          // InterfaceMethod java/sql/Connection.close:()V
      71: ireturn       
      72: astore_3      
      73: aload         6
      75: ifnull        85
      78: aload         6
      80: invokeinterface #139,  1          // InterfaceMethod java/sql/PreparedStatement.close:()V
      85: aload_3       
      86: athrow        
      87: astore        4
      89: aload_3       
      90: ifnonnull     99
      93: aload         4
      95: astore_3      
      96: goto          111
      99: aload_3       
     100: aload         4
     102: if_acmpeq     111
     105: aload_3       
     106: aload         4
     108: invokevirtual #143                // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
     111: aload         5
     113: ifnull        123
     116: aload         5
     118: invokeinterface #142,  1          // InterfaceMethod java/sql/Connection.close:()V
     123: aload_3       
     124: athrow        
     125: astore        4
     127: aload_3       
     128: ifnonnull     137
     131: aload         4
     133: astore_3      
     134: goto          149
     137: aload_3       
     138: aload         4
     140: if_acmpeq     149
     143: aload_3       
     144: aload         4
     146: invokevirtual #143                // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
     149: aload_3       
     150: athrow        
     151: astore_3      
     152: new           #25                 // class java/lang/RuntimeException
     155: dup           
     156: aload_3       
     157: invokespecial #27                 // Method java/lang/RuntimeException."<init>":(Ljava/lang/Throwable;)V
     160: athrow        
    Exception table:
       from    to  target type
          24    47    72   any
          71    72    72   any
          14    59    87   any
          71    87    87   any
           8   125   125   any
           3    71   151   Class java/sql/SQLException
          72   151   151   Class java/sql/SQLException

答案 20 :(得分:10)

另一种方式是创建一个包含相同字段的新表,使用创建唯一索引。然后将所有数据从旧表移动到新表。自动SQL SERVER忽略(如果存在重复值,还有一个关于该怎么做的选项:ignore,interrupt或sth)重复值。所以我们有相同的表没有重复的行。 如果您不想要唯一索引,则可以在传输数据之后将其删除

特别是对于较大的表 ,您可以使用DTS(SSIS包导入/导出数据),以便将所有数据快速传输到新的唯一索引表。对于700万行,只需几分钟。

答案 21 :(得分:9)

通过使用以下查询,我们可以根据单列或多列删除重复记录。以下查询是基于两列删除。表名是:testing和列名empno,empname

DELETE FROM testing WHERE empno not IN (SELECT empno FROM (SELECT empno, ROW_NUMBER() OVER (PARTITION BY empno ORDER BY empno) 
AS [ItemNumber] FROM testing) a WHERE ItemNumber > 1)
or empname not in
(select empname from (select empname,row_number() over(PARTITION BY empno ORDER BY empno) 
AS [ItemNumber] FROM testing) a WHERE ItemNumber > 1)

答案 22 :(得分:9)

  1. 创建具有相同结构的新空白表

  2. 执行此类查询

    INSERT INTO tc_category1
    SELECT *
    FROM tc_category
    GROUP BY category_id, application_id
    HAVING count(*) > 1
    
  3. 然后执行此查询

    INSERT INTO tc_category1
    SELECT *
    FROM tc_category
    GROUP BY category_id, application_id
    HAVING count(*) = 1
    

答案 23 :(得分:9)

这是删除重复记录的最简单方法

 DELETE FROM tblemp WHERE id IN 
 (
  SELECT MIN(id) FROM tblemp
   GROUP BY  title HAVING COUNT(id)>1
 )

http://askme.indianyouth.info/details/how-to-dumplicate-record-from-table-in-using-sql-105

答案 24 :(得分:7)

DELETE
FROM
    table_name T1
WHERE
    rowid > (
        SELECT
            min(rowid)
        FROM
            table_name T2
        WHERE
            T1.column_name = T2.column_name
    );

答案 25 :(得分:7)

我会提到这种方法以及它可能会有所帮助,并适用于所有SQL服务器: 通常只有一个 - 两个重复,并且Ids和重复计数是已知的。在这种情况下:

SET ROWCOUNT 1 -- or set to number of rows to be deleted
delete from myTable where RowId = DuplicatedID
SET ROWCOUNT 0

答案 26 :(得分:7)

  

从应用程序级别(不幸的是)。我同意防止重复的正确方法是在数据库级别通过使用唯一索引,但在SQL Server 2005中,索引只允许900字节,而我的varchar(2048)字段将其吹走。< / p>

我不知道它的表现如何,但我认为你可以写一个触发器来强制执行,即使你不能直接用索引来做。类似的东西:

-- given a table stories(story_id int not null primary key, story varchar(max) not null)
CREATE TRIGGER prevent_plagiarism 
ON stories 
after INSERT, UPDATE 
AS 
    DECLARE @cnt AS INT 

    SELECT @cnt = Count(*) 
    FROM   stories 
           INNER JOIN inserted 
                   ON ( stories.story = inserted.story 
                        AND stories.story_id != inserted.story_id ) 

    IF @cnt > 0 
      BEGIN 
          RAISERROR('plagiarism detected',16,1) 

          ROLLBACK TRANSACTION 
      END 

另外,varchar(2048)听起来很腥(生活中的一些东西是2048字节,但这种情况非常罕见);它真的不是varchar(max)吗?

答案 27 :(得分:6)

DELETE 
FROM MyTable
WHERE NOT EXISTS (
              SELECT min(RowID)
              FROM Mytable
              WHERE (SELECT RowID 
                     FROM Mytable
                     GROUP BY Col1, Col2, Col3
                     ))
               );

答案 28 :(得分:6)

CREATE TABLE car(Id int identity(1,1), PersonId int, CarId int)

INSERT INTO car(PersonId,CarId)
VALUES(1,2),(1,3),(1,2),(2,4)

--SELECT * FROM car

;WITH CTE as(
SELECT ROW_NUMBER() over (PARTITION BY personid,carid order by personid,carid) as rn,Id,PersonID,CarId from car)

DELETE FROM car where Id in(SELECT Id FROM CTE WHERE rn>1)

答案 29 :(得分:6)

我想要预览要删除的行,并控制要保留的重复行。见http://developer.azurewebsites.net/2014/09/better-sql-group-by-find-duplicate-data/

with MYCTE as (
  SELECT ROW_NUMBER() OVER (
    PARTITION BY DuplicateKey1
                ,DuplicateKey2 -- optional
    ORDER BY CreatedAt -- the first row among duplicates will be kept, other rows will be removed
  ) RN
  FROM MyTable
)
DELETE FROM MYCTE
WHERE RN > 1

答案 30 :(得分:6)

另一种方法: -

DELETE A
FROM   TABLE A,
       TABLE B
WHERE  A.COL1 = B.COL1
       AND A.COL2 = B.COL2
       AND A.UNIQUEFIELD > B.UNIQUEFIELD 

答案 31 :(得分:1)

alter table MyTable add sno int identity(1,1)
    delete from MyTable where sno in
    (
    select sno from (
    select *,
    RANK() OVER ( PARTITION BY RowID,Col3 ORDER BY sno DESC )rank
    From MyTable
    )T
    where rank>1
    )

    alter table MyTable 
    drop  column sno

答案 32 :(得分:1)

我知道这个问题已经回答了,但我已经创建了非常有用的sp,它将为表重复创建一个动态删除语句:

    CREATE PROCEDURE sp_DeleteDuplicate @tableName varchar(100), @DebugMode int =1
AS 
BEGIN
SET NOCOUNT ON;

IF(OBJECT_ID('tempdb..#tableMatrix') is not null) DROP TABLE #tableMatrix;

SELECT ROW_NUMBER() OVER(ORDER BY name) as rn,name into #tableMatrix FROM sys.columns where [object_id] = object_id(@tableName) ORDER BY name

DECLARE @MaxRow int = (SELECT MAX(rn) from #tableMatrix)
IF(@MaxRow is null)
    RAISERROR  ('I wasn''t able to find any columns for this table!',16,1)
ELSE 
    BEGIN
DECLARE @i int =1 
DECLARE @Columns Varchar(max) ='';

WHILE (@i <= @MaxRow)
BEGIN 
    SET @Columns=@Columns+(SELECT '['+name+'],' from #tableMatrix where rn = @i)

    SET @i = @i+1;
END

---DELETE LAST comma
SET @Columns = LEFT(@Columns,LEN(@Columns)-1)

DECLARE @Sql nvarchar(max) = '
WITH cteRowsToDelte
     AS (
SELECT ROW_NUMBER() OVER (PARTITION BY '+@Columns+' ORDER BY ( SELECT 0)) as rowNumber,* FROM '+@tableName
+')

DELETE FROM cteRowsToDelte
WHERE  rowNumber > 1;
'
SET NOCOUNT OFF;
    IF(@DebugMode = 1)
       SELECT @Sql
    ELSE
       EXEC sp_executesql @Sql
    END
END

所以如果你创建这样的表:

IF(OBJECT_ID('MyLitleTable') is not null)
    DROP TABLE MyLitleTable 


CREATE TABLE MyLitleTable
(
    A Varchar(10),
    B money,
    C int
)
---------------------------------------------------------

    INSERT INTO MyLitleTable VALUES
    ('ABC',100,1),
    ('ABC',100,1), -- only this row should be deleted
    ('ABC',101,1),
    ('ABC',100,2),
    ('ABCD',100,1)

    -----------------------------------------------------------

     exec sp_DeleteDuplicate 'MyLitleTable',0

它将删除表中的所有重复项。如果在没有第二个参数的情况下运行它,它将返回一个要运行的SQL语句。

如果您需要排除任何列,只需在调试模式下运行它,获取代码并随意修改它。

答案 33 :(得分:1)

有时会使用软删除机制,其中记录日期以指示删除的日期。在这种情况下,可以使用UPDATE语句根据重复条目更新此字段。

UPDATE MY_TABLE
   SET DELETED = getDate()
 WHERE TABLE_ID IN (
    SELECT x.TABLE_ID
      FROM MY_TABLE x
      JOIN (SELECT min(TABLE_ID) id, COL_1, COL_2, COL_3
              FROM MY_TABLE d
             GROUP BY d.COL_1, d.COL_2, d.COL_3
            HAVING count(*) > 1) AS d ON d.COL_1 = x.COL_1
                                     AND d.COL_2 = x.COL_2
                                     AND d.COL_3 = x.COL_3
                                     AND d.TABLE_ID <> x.TABLE_ID
             /*WHERE x.COL_4 <> 'D' -- Additional filter*/)

这种方法适用于相当温和的表,包含大约3000万行,重复次数很高和很少。

答案 34 :(得分:0)

现在让我们看看弹性搜索表,这个表有重复的行,Id是相同的uniq字段。我们知道如果某个ID存在于组标准中,那么我们可以删除该组的其他行。我的态度表明了这个标准。

这个帖子的很多情况都属于我的状态。只需根据您的情况更改目标组标准,以删除重复(重复)的行。

DELETE 
FROM elasticalsearch
WHERE Id NOT IN 
               (SELECT min(Id)
                     FROM elasticalsearch
                     GROUP BY FirmId,FilterSearchString
                     ) 

欢呼声

答案 35 :(得分:0)

我认为这会有所帮助。在这里, ROW_NUMBER()OVER(PARISTION BY res1.Title ORDER BY res1.Id)为num 已用于区分重复的行。

delete FROM
(SELECT res1.*,ROW_NUMBER() OVER(PARTITION BY res1.Title ORDER BY res1.Id)as num
 FROM 
(select * from [dbo].[tbl_countries])as res1
)as res2
WHERE res2.num > 1

答案 36 :(得分:0)

如果重复行中的所有列都相同,则可以使用下面的查询删除重复记录。

SELECT DISTINCT * INTO #TemNewTable FROM #OriginalTable
TRUNCATE TABLE #OriginalTable
INSERT INTO #OriginalTable SELECT * FROM #TemNewTable
DROP TABLE #TemNewTable

答案 37 :(得分:0)

用于表结构

MyTable

RowID int not null identity(1,1) primary key,
Col1 varchar(20) not null,
Col2 varchar(2048) not null,
Col3 tinyint not null

用于删除重复项的查询:

DELETE t1
FROM MyTable t1
INNER JOIN MyTable t2
WHERE t1.RowID > t2.RowID
  AND t1.Col1 = t2.Col1
  AND t1.Col2=t2.Col2
  AND t1.Col3=t2.Col3;

我假设RowID是一种自动递增,其余列具有重复值。

答案 38 :(得分:0)

基于两列删除重复项的其他方法

我发现这个查询更易于阅读和替换。

DELETE 
FROM 
 TABLE_NAME 
 WHERE FIRST_COLUMNS 
 IN( 
       SELECT * FROM 
           ( SELECT MIN(FIRST_COLUMNS) 
             FROM TABLE_NAME 
             GROUP BY 
                      FIRST_COLUMNS,
                      SECOND_COLUMNS 
             HAVING COUNT(FIRST_COLUMNS) > 1 
            ) temp 
   )

注意:运行前最好先simulate query

enter image description here

答案 39 :(得分:0)

在postgresql中删除表重复行的一种非常简单的方法。

DELETE FROM table1 a
USING table1 b
WHERE a.id < b.id
AND a.column1 = b.column1
AND a.column2 = b.column2;