【问题标题】:Why isn't this working to remove duplicates为什么这不能删除重复项
【发布时间】:2019-07-27 13:04:52
【问题描述】:

我正在使用 MySQL,但现在我正在尝试使用 MS SQL (2016) 做类似的事情,但查询不起作用。我有表“TEST”,我正在尝试根据列“lastname, firstname”匹配删除重复项。

使用最低的 ID 值:

DELETE FROM TEST
WHERE lastname NOT IN (
  SELECT t.id FROM ( 
    SELECT MIN(PersonID) id
    FROM TEST
    GROUP BY lastname, firstname
  ) t
)

这些列是:“PersonID”“LastName”“FirstName”“Address”“City”

错误:

Msg 245, Level 16, State 1, Line 1 转换时转换失败 将 varchar 值 'JOHN' 转换为数据类型 int。

【问题讨论】:

  • 对不起!错误如下:Msg 245, Level 16, State 1, Line 1 Conversion failed when convert the varchar value 'JOHN' to data type int.

标签: sql sql-server database


【解决方案1】:

您想保留具有最小 id 的行对吗?使用EXISTS:

delete t from test t
where exists (
  select 1 from test
  where firstname = t.firstname and lastname = t.lastname
  and id < t.id
)

【讨论】:

  • 是的,第一个出现的应该是留下的。我收到“消息 102,第 15 级,状态 1,第 1 行 't' 附近的语法不正确。”。我不完全明白为什么。
  • 你改成:delete t from test t
  • 你说得对,这行得通,我理解。谢谢!
【解决方案2】:

您将姓氏与 ID 进行比较,因此您报告了错误“Conversion failed when convert the varchar value 'JOHN' to data type int”试试这个:

DELETE FROM TEST
WHERE PersonID NOT IN (
  SELECT t.id FROM ( 
    SELECT MIN(PersonID) id
    FROM TEST
    GROUP BY lastname, firstname
  ) t
)

【讨论】:

    【解决方案3】:

    在 SQL Server 中,我建议为此使用窗口函数:

    with todelete as (
          select t.*,
                 row_number() over (partition by firstname, lastname order by id) as seqnum
          from test t
         ) 
    delete from todelete
        where seqnum > 1;
    

    【讨论】:

    • 这绝对有效,但我对 SQL Server 的了解还不够,无法完全理解它。这是一种更有效的方法来说明 Forpas 是如何做到的?谢谢!
    • @Natsu。 . .这是一个有趣的问题。您需要在您的数据上对其进行测试。一般来说,我认为它会更快,但在某些情况下,exists 子句可能会。
    • 它不会让我投票赞成您的回复,因为我还是新手,对不起。不过,我非常感谢您的帮助。
    【解决方案4】:

    您可以尝试将您的 ID 转换为 varchar/nvarchar,因为 lastname 是一个字符。虽然您可能会仔细检查您是否应该引用 PersonID 或姓氏。

    DELETE FROM TEST
    WHERE lastname NOT IN (
      SELECT CONVERT(VARCHAR(50),t.id) FROM ( 
        SELECT MIN(PersonID) id
        FROM TEST
        GROUP BY lastname, firstname
      ) t
    )
    

    【讨论】:

      【解决方案5】:

      你也可以试试这个方法:

      DELETE T2 FROM ( 
          SELECT 
              MIN(PersonID) id
          FROM 
              TEST
          GROUP BY 
              lastname, firstname
        ) t
      INNER JOIN TEST T2 ON t.id = T2.PersonID
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-06
        • 1970-01-01
        相关资源
        最近更新 更多