【问题标题】:Delete duplicate records without using ROW_NUMBER() function不使用 ROW_NUMBER() 函数删除重复记录
【发布时间】:2016-06-01 06:02:58
【问题描述】:

我想删除重复记录而不使用 ROW_NUMBER() 函数 (SQL Server)

示例:包含以下数据的表格:

name     salary
-----------------
Husain   20000.00
Husain   20000.00
Husain   20000.00
Munavvar 50000.00
Munavvar 50000.00

删除重复记录后 表应该包含这样的数据:

name     salary
-----------------
Husain   20000.00
Munavvar 50000.00

【问题讨论】:

  • 你至少有身份证吗?
  • 使用Row_Number()有什么问题?
  • 没有只有两列(姓名,工资)。面试官在我最近的采访中问了我这个问题。

标签: sql sql-server


【解决方案1】:

因为这个问题的动机似乎是学术兴趣而不是实际用途......

该表没有主键,但未记录的伪列 %%physloc%% 可以提供替代。

DELETE T1
FROM YourTable T1 WITH(TABLOCKX)
WHERE CAST(T1.%%physloc%% AS BIGINT)
NOT IN (SELECT MAX(CAST(%%physloc%% AS BIGINT))
        FROM YourTable 
        GROUP BY Name, Salary)

实际上,您永远不应该使用上述和just use row_number,因为它更有效且有文档记录。

(Data Explorer Demo)

【讨论】:

  • 谢谢马丁的回答。
【解决方案2】:

另一个(学术)选项,取决于您使用的 SQL Server 版本:

;with CTE as (select lag(name) over (order by name) as name1
              ,lag(salary) over (order by name) as salary1
              , * 
              from #table)

delete from cte where name = name1 and salary = salary1

【讨论】:

    【解决方案3】:

    您可以像这样使用Common Table ExpressionROW_NUMBER() 结合使用(这是删除重复项的最佳方法):

    WITH CTE AS(
       SELECT t.name,t.salary
              ROW_NUMBER() OVER(PARTITION BY t.name,t.salary ORDER BY (SELECT 1)) as rn
       FROM YourTable t
    )
    DELETE FROM CTE WHERE RN > 1
    

    ROW_NUMBER() 会为每个组随机分配排名,只有一个会获得排名1 ,其他的都会被删除。

    编辑:我可以在不使用ROW_NUMBER() 的情况下提出其他建议:

    SELECT distinct t.name,t.salart
    INTO TEMP_FOR_UPDATE
    FROM YourTable t;
    
    TRUNCATE TABLE YourTable ;
    
    INSERT INTO YourTable 
    SELECT * FROM TEMP_FOR_UPDATE;
    
    DROP TEMP_FOR_UPDATE;
    

    这将基本上创建一个包含表中不同值的临时表,截断表并将不同值重新插入表中。

    【讨论】:

    • 没有的哪一部分你不明白?
    • @sagi 我认为你需要删除这个答案。
    • @Munavvar 我还添加了一个没有ROW_NUMBER()的解决方案
    • @sagi,我建议改用TRUNCATE
    • 您的更新不是有效的 SQL Server 语法。 SQL Server 中没有create table ... As query。等效为select ... Into。此外,SQL Server 不允许在行号中使用 ORDER BY 1,但允许 ORDER BY (SELECT 1)
    【解决方案4】:
    1. 使用group by name , salary(或 distinct)。
    2. 插入临时表。
    3. 删除原始数据
    4. 将临时表中的数据复制到原始表中

    【讨论】:

      【解决方案5】:

      在 oracle 中你可以如下使用

      从表中删除 where rowid not in (select max(rowid) from test group by name,salary);

      【讨论】:

      • 问题是关于 SQL Server 的。
      • 否则你遵循如下创建临时表emp_temp As Select Distinct name,salary From emp_temp;截断表emp;插入 emp Select * From emp_temp;
      • 人们如此渴望给出否定标志..我同意答案是无关紧要的,但@Temruzinn 已经说过它的预言......我正在摆脱至少一个否定
      猜你喜欢
      • 2021-07-18
      • 1970-01-01
      • 1970-01-01
      • 2014-04-04
      • 1970-01-01
      • 2011-07-28
      • 2012-04-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多