【问题标题】:Deleting duplicates from same SQL table从同一个 SQL 表中删除重复项
【发布时间】:2021-02-05 12:42:32
【问题描述】:

我的表如下所示(在 SQL Server 2016 SP2 中):

KEY | CN_ID | CNO_IND
----+-------+--------
001 | P001  | N
002 | P001  | Y
003 | P001  | N
005 | P002  | N
006 | P002  | N
007 | P004  | N
008 | P004  | Y
009 | P004  | N
010 | P004  | Y

这是我想做的:

对于所有 CNO_IND = 'Y' 的 CN_ID,我想删除所有 CNO_IND = 'N' 的 CN_ID。

我的最终结果会是这样的:

KEY | CN_ID | CNO_IND
----+-------+--------
002 | P001  | Y
005 | P002  | N
006 | P002  | N
008 | P004  | Y
010 | P004  | Y

如您所见,P002 不会被删除,因为 P002 中没有一个 CNO_IND = 'Y'。 P004 仍然有重复项,因为我想保留 CNO_IND = 'Y' 的所有记录并删除 CNO_IND = 'N' 的重复项。

希望为此找到最佳解决方案。

提前致谢

【问题讨论】:

    标签: sql sql-server duplicates subquery sql-delete


    【解决方案1】:

    一个选项使用exists

    delete t
    from mytable t
    where cno_ind = 'N' and exists (
        select 1 from mytable t1 where t1.cn_id = t.cn_id and t1.cno_ind = 'Y'
    )
    

    【讨论】:

      【解决方案2】:

      你可以使用 CTE 这样的东西

      With CTE as (
      Select KEY, CN_ID, CNO_IND, Row_Number() over (Partition by CN_ID  Order By CN_ID) as rnk from YourTable
      )
      
      Delete from CTE where rnk > 1
      

      【讨论】:

      • 这将删除我想要保留的 CNO_IND = 'Y' 的记录以及 P002 之一。
      • 这个答案不正确。我很惊讶它被赞成了。
      【解决方案3】:

      但你仍然可以使用 CTE 做到这一点:

      With del as (
        Select
          [KEY], CN_ID, CNO_IND,
          max(case CNO_IND when 'Y' then 'Y' end) over (Partition by CN_ID) as has_y
        from tab
      )
      
      delete
      from del
      where has_y = 'Y'
        and cno_ind = 'N'
      

      Fiddle

      在您的示例结果中,您为 P002 留下了重复项,尽管您需要删除重复的 N,但它只有 N,所以我也没有删除只有 N 的 N 的重复项。

      【讨论】:

      • 是的,如果 CN_ID 没有 Y ,我想保留它们。一旦它有一个 Y,只删除带有 N 的重复项。
      • 我认为这可行,但我收到一条警告消息。
      • @AzLateef DBMS 只是告诉您它是如何工作的,但如果您了解 SQL,您就会知道聚合函数会忽略空值。您可以在我提供的小提琴中进行测试,无需猜测它是否有效。
      猜你喜欢
      • 2014-01-15
      • 1970-01-01
      • 2011-05-29
      • 2020-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多