如何删除sql server中的重复行?

Fea*_*hal 379 mysql sql duplicates sql-server-2008 sql-delete

我怎么能unique row idunique row id存在?

我的桌子是

col1  col2 col3 col4 col5 col6 col7
john  1    1    1    1    1    1 
john  1    1    1    1    1    1
sally 2    2    2    2    2    2
sally 2    2    2    2    2    2
Run Code Online (Sandbox Code Playgroud)

我希望在重复删除后留下以下内容:

john  1    1    1    1    1    1
sally 2    2    2    2    2    2
Run Code Online (Sandbox Code Playgroud)

我已经尝试了一些查询,但我认为它们依赖于行ID,因为我没有得到理想的结果.例如:

DELETE
FROM table
WHERE col1 IN (
    SELECT id
    FROM table
    GROUP BY id
    HAVING (COUNT(col1) > 1)
)
Run Code Online (Sandbox Code Playgroud)

Tim*_*ter 743

我喜欢CTE,ROW_NUMBER因为这两个组合允许我们查看哪些行被删除(或更新),因此只需更改DELETE FROM CTE...SELECT * FROM CTE:

WITH CTE AS(
   SELECT [col1], [col2], [col3], [col4], [col5], [col6], [col7],
       RN = ROW_NUMBER()OVER(PARTITION BY col1 ORDER BY col1)
   FROM dbo.Table1
)
DELETE FROM CTE WHERE RN > 1
Run Code Online (Sandbox Code Playgroud)

DEMO (结果不同;我认为这是由于你的错字)

COL1    COL2    COL3    COL4    COL5    COL6    COL7
john    1        1       1       1       1       1
sally   2        2       2       2       2       2
Run Code Online (Sandbox Code Playgroud)

此示例col1由于单个列确定重复项PARTITION BY col1.如果要包含多个列,只需将它们添加到PARTITION BY:

ROW_NUMBER()OVER(PARTITION BY Col1, Col2, ... ORDER BY OrderColumn)
Run Code Online (Sandbox Code Playgroud)

  • 此答案仅删除col1中具有重复项的行.将"select"中的列添加到"partition by",例如使用答案中的select:RN = ROW_NUMBER()OVER(PARTITION BY col1,col2,col3,col4,col5,col6,col7 ORDER BY col1) (15认同)
  • 谢谢你的回答.相比之下,MSFT的答案非常复杂:http://stackoverflow.com/questions/18390574/how-to-delete-duplicate-rows-in-sql-server (2认同)
  • @ omachu23:在这种情况下它并不重要,虽然我认为它在CTE中比在外面更有效(`AND COl1 ='John'`).通常您应该在CTE中应用过滤器. (2认同)
  • CTE 是什么意思,当我输入它时,我收到 sql 错误。 (2认同)

Sha*_*r K 153

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

强烈建议遵循这篇文章:: 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
Run Code Online (Sandbox Code Playgroud)

没有保持原创

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)
Run Code Online (Sandbox Code Playgroud)

  • @Bigeyes从CTE删除记录将从实际物理表中删除相应的记录。(因为CTE包含对实际记录的引用)。 (5认同)
  • 为什么要删除原始文件及其副本?我不明白为什么您不想删除重复项并保留另一个。 (3认同)
  • 窗口功能是一个很好的解决方案. (2认同)
  • 我有点困惑。您从CTE而不是原始表中删除了它。那么它是怎样工作的? (2认同)
  • 错误:关系“cte”不存在 (2认同)

Aam*_*mir 46

没有使用CTE,ROW_NUMBER()你可以只删除记录,只需使用group by with MAXfunction here和example

DELETE
FROM MyDuplicateTable
WHERE ID NOT IN
(
SELECT MAX(ID)
FROM MyDuplicateTable
GROUP BY DuplicateColumn1, DuplicateColumn2, DuplicateColumn3)
Run Code Online (Sandbox Code Playgroud)

  • 仅当_是_id/unique字段时才有效. (9认同)
  • 这很好,谢谢.@DerekSmalls这不会删除我的非重复记录. (8认同)
  • 此查询将删除非重复记录. (4认同)
  • 或者您可以使用“MIN(ID)”保留原始记录 (2认同)
  • 虽然这可能在很多情况下都有效,但问题明确指出没有唯一的 ID。 (2认同)

小智 16

DELETE from search
where id not in (
   select min(id) from search
   group by url
   having count(*)=1

   union

   SELECT min(id) FROM search
   group by url
   having count(*) > 1
)
Run Code Online (Sandbox Code Playgroud)

  • 我不相信有任何需要使用具有或联合,这就足够了:从搜索中删除 id 不在的位置(从搜索组中按 url 选择 min(id)) (2认同)

San*_*isy 10

要从 SQL Server 中的表中删除重复行,请执行以下步骤:

  1. 使用 GROUP BY 子句或 ROW_NUMBER() 函数查找重复行。
  2. 使用 DELETE 语句删除重复的行。

设置样本表

DROP TABLE IF EXISTS contacts;

CREATE TABLE contacts(
    contact_id INT IDENTITY(1,1) PRIMARY KEY,
    first_name NVARCHAR(100) NOT NULL,
    last_name NVARCHAR(100) NOT NULL,
    email NVARCHAR(255) NOT NULL,
);
Run Code Online (Sandbox Code Playgroud)

插入值

INSERT INTO contacts
    (first_name,last_name,email) 
VALUES
    ('Syed','Abbas','syed.abbas@example.com'),
    ('Catherine','Abel','catherine.abel@example.com'),
    ('Kim','Abercrombie','kim.abercrombie@example.com'),
    ('Kim','Abercrombie','kim.abercrombie@example.com'),
    ('Kim','Abercrombie','kim.abercrombie@example.com'),
    ('Hazem','Abolrous','hazem.abolrous@example.com'),
    ('Hazem','Abolrous','hazem.abolrous@example.com'),
    ('Humberto','Acevedo','humberto.acevedo@example.com'),
    ('Humberto','Acevedo','humberto.acevedo@example.com'),
    ('Pilar','Ackerman','pilar.ackerman@example.com');
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

询问

    SELECT 
   contact_id, 
   first_name, 
   last_name, 
   email
FROM 
   contacts;
Run Code Online (Sandbox Code Playgroud)

从表中删除重复行

   WITH cte AS (
    SELECT 
        contact_id, 
        first_name, 
        last_name, 
        email, 
        ROW_NUMBER() OVER (
            PARTITION BY 
                first_name, 
                last_name, 
                email
            ORDER BY 
                first_name, 
                last_name, 
                email
        ) row_num
     FROM 
        contacts
)
DELETE FROM cte
WHERE row_num > 1;
Run Code Online (Sandbox Code Playgroud)

现在应该删除该记录

在此输入图像描述


Mah*_*our 8

有两种解决方案mysql

A)使用DELETE JOIN语句删除重复行

DELETE t1 FROM contacts t1
INNER JOIN contacts t2 
WHERE 
    t1.id < t2.id AND 
    t1.email = t2.email;
Run Code Online (Sandbox Code Playgroud)

此查询两次引用联系人表,因此,它使用表别名t1t2

输出是:

1 次查询正常,4 行受影响(0.10 秒)

如果要删除重复行并保留lowest id,可以使用以下语句:

DELETE c1 FROM contacts c1
INNER JOIN contacts c2 
WHERE
    c1.id > c2.id AND 
    c1.email = c2.email;
Run Code Online (Sandbox Code Playgroud)

   

B)使用中间表删除重复行

下面显示了使用中间表删除重复行的步骤:

    1.新建一个与原表结构相同的表,要删除重复行。

    2. 将原始表中的不同行插入到直接表中。

    3. 将原始表中的不同行插入到直接表中。

 

Step 1. 创建一个与原表结构相同的新表:

CREATE TABLE source_copy LIKE source;
Run Code Online (Sandbox Code Playgroud)

步骤 2. 将原始表中的不同行插入到新表中:

INSERT INTO source_copy
SELECT * FROM source
GROUP BY col; -- column that has duplicate values
Run Code Online (Sandbox Code Playgroud)

步骤 3. 删除原始表并将直接表重命名为原始表

DROP TABLE source;
ALTER TABLE source_copy RENAME TO source;
Run Code Online (Sandbox Code Playgroud)

来源:http : //www.mysqltutorial.org/mysql-delete-duplicate-rows/


小智 7

如果没有引用(例如外键),则可以执行此操作。测试概念证明和测试数据重复时,我会做很多事情。

SELECT DISTINCT [col1],[col2],[col3],[col4],[col5],[col6],[col7]

INTO [newTable]
Run Code Online (Sandbox Code Playgroud)

进入对象资源管理器并删除旧表。

用旧表的名称重命名新表。

  • 很好奇当 [oldTable] 有数十亿行时这个答案如何表现良好...... (2认同)
  • 这会烧毁固态硬盘上的 TBW,不推荐。 (2认同)

oab*_*rca 6

微软有一个关于如何删除重复项的完整指南.查看 http://support.microsoft.com/kb/139444

简而言之,当您只删除几行时,这是删除重复项的最简单方法:

SET rowcount 1;
DELETE FROM t1 WHERE myprimarykey=1;
Run Code Online (Sandbox Code Playgroud)

myprimarykey是行的标识符.

我将rowcount设置为1,因为我只有两行是重复的.如果我有3行重复,那么我将rowcount设置为2,以便它删除它看到的前两个,只留下表t1中的一个.

希望它能帮助任何人


Jit*_*aji 6

请看下面的删除方式.

Declare @table table
(col1 varchar(10),col2 int,col3 int, col4 int, col5 int, col6 int, col7 int)
Insert into @table values 
('john',1,1,1,1,1,1),
('john',1,1,1,1,1,1),
('sally',2,2,2,2,2,2),
('sally',2,2,2,2,2,2)
Run Code Online (Sandbox Code Playgroud)

创建了一个名为的示例表@table,并使用给定的数据加载它.

在此输入图像描述

Delete  aliasName from (
Select  *,
        ROW_NUMBER() over (Partition by col1,col2,col3,col4,col5,col6,col7 order by col1) as rowNumber
From    @table) aliasName 
Where   rowNumber > 1

Select * from @table
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

注意:如果要给出部件中的所有列Partition by,则order by没有太大意义.

我知道,这个问题是在三年前提出来的,我的回答是蒂姆发布的另一个版本,但是发布只是对任何人都有帮助.


小智 5

尝试使用:

SELECT linkorder
    ,Row_Number() OVER (
        PARTITION BY linkorder ORDER BY linkorder DESC
        ) AS RowNum
FROM u_links
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明


小智 5

在sql server中可以通过多种方式完成,最简单的方法是:将重复行表中的不同行插入到新的临时表中。然后删除重复行表中的所有数据,然后插入没有重复的临时表中的所有数据,如下所示。

select distinct * into #tmp From table
   delete from table
   insert into table
   select * from #tmp drop table #tmp

   select * from table
Run Code Online (Sandbox Code Playgroud)

使用通用表表达式(CTE)删除重复行

With CTE_Duplicates as 
(select id,name , row_number() 
over(partition by id,name order by id,name ) rownumber  from table  ) 
delete from CTE_Duplicates where rownumber!=1
Run Code Online (Sandbox Code Playgroud)


epo*_*pox 5

删除所有重复项,但第一个(带最小 ID)

应该和其他 SQL 服务器一样工作,比如 Postgres:

DELETE FROM table
WHERE id NOT IN (
   select min(id) from table
   group by col1, col2, col3, col4, col5, col6, col7
)
Run Code Online (Sandbox Code Playgroud)

  • @SergeMerzliakov,它是行的主键。当没有唯一密钥时,这个答案不应该起作用...但是,大多数读者在一般情况下都拥有它,因此“id”对他们来说应该有意义。 (3认同)
  • 即使不存在显式的“id”列,您也可以使用自动生成的“ctid”PostgreSQL行标识符:/sf/ask/1023853701/ 在 SQLite 中它称为“rowid”:/sf/ask/573337901/ (2认同)