【问题标题】:Finding duplicate values in a table where all the columns are not the same在所有列都不相同的表中查找重复值
【发布时间】:2019-05-20 13:37:45
【问题描述】:

我正在处理表格中的一组数据。 为简单起见,我有如下表格和一些示例数据:

此表中的一些数据来自不同的来源,这些数据是具有cqmRecordID != null的数据

我需要在此表中查找重复值并删除从其他来源(具有 cqmRecordID 的那些)传来的重复值 如果这些列的值相同,则记录被认为是重复的:

  • [姓名]
  • 演员([CreatedDate] as Date)
  • [创建者]

所以在我上面的示例数据中,记录#5 和记录#6 将被视为重复。

作为解决方案,我提出了以下两个查询:

查询 #1:

 select * from (
  select recordid, cqmrecordid, ROW_NUMBER() over (partition by name, cast(createddate as date), createdby 
                                                   order by cqmrecordid, recordid) as rownum
  from vmsNCR  ) A
  where cqmrecordid is not null   
  order by recordid

查询 #2:

  select A.recordID, A.cqmRecordID, B.RecordID, B.cqmRecordID 
  from vmsNCR A 
  join vmsNCR B
    on A.Name = B.Name 
    and cast(A.CreatedDate as date) = cast(B.CreatedDate as date) 
    and A.CreatedBy = B.CreatedBy
    and A.RecordID != B.RecordID 
    and A.cqmRecordID is not null 
  order by A.RecordID

有没有更好的方法来解决这个问题?一个比另一个性能更好吗?

【问题讨论】:

  • 那么这些查询有什么问题?
  • @JuanCarlosOropeza 的查询没有问题.. 但只是想知道这是否是最好的方法.. 这只是样本数据.. 我会有一个大数据集。
  • 性能问题应该包括EXPLAIN和一些关于表大小、索引、当前时间性能、期望时间等的信息。Slow是一个相对术语,我们需要一个真实的值来比较。
  • 没有{1,3} 也重复?
  • @JuanCarlosOropeza no .. 这些不会重复.. 因为我只认为一条记录来自不同的数据源(cqmRecordNumber 不为空)

标签: sql sql-server


【解决方案1】:

如果你想获取所有没有重复的行,那么:

select t.*  -- or all columns except seqnum
from (select t.*,
             row_number() over (partition by name, cast(createddate as date), createdby
                                order by (case when cqmRecordId is not null then 1 else 2 end)
                               ) as seqnum
      from t
     ) t
where seqnum = 1;

如果您想要性能,请创建一个列,然后创建一个索引:

alter table t add cqmRecordId_flag as (case when cqmRecordId is null then 0 else 1 end) persisted;
alter table t add createddate_date as (cast(createddate as date)) persisted;

然后是一个索引:

create index idx_t_4 on t(name, createddate_date, createdby, cqmRecordId_flag desc);

编辑:

如果您实际上只是想从表中删除 NULL 值,您可以使用:

delete t from t
    where t.cqmRecordId is null and
          exists (select 1
                  from t t2
                  where t2.name = t.name and
                        convert(date, t2.createddate_date) =convert(date, t.createddate_date) and
                        t2.createdby = t.createdby and
                        t2.cqmRecordId is not null
                 );

您可以使用与select 相同的逻辑来选择重复项。

【讨论】:

  • 也许你想使用 rank() 而不是 row_number() 以防多个重复?
  • 这也带来了没有重复的。
  • @JuanCarlosOropeza 。 . .我假设 OP 真的想获取没有重复的行,但我更新了答案。
  • 看 OP 的愿望结果(在图片中)他返回 {5,6} 他认为是重复项
  • 他想删除不为空的重复项。所以逻辑颠倒了。
【解决方案2】:

试试下面的查询它可能对你有用

;WITH TestCTE
AS
(
   SELECT *,ROW_NUMBER() OVER(
              PARTITION BY [Name],Cast([CreatedDate] as Date),[CreatedBy] 
              ORDER BY RecordId
            ) AS RowNumber
)
DELETE FROM TestCTE
WHERE RowNumber > 1

【讨论】:

    【解决方案3】:

    使用以下代码消除重复项

    ;WITH CTE
    AS
    (
       SELECT ROW_NUMBER() OVER(
                  PARTITION BY [Name],Cast([CreatedDate] as Date),[CreatedBy] 
                  ORDER BY cqmRecordId
               ) AS Rnk
       ,*
    )
    DELETE FROM CTE
    WHERE Rnk <> 1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-12-05
      • 2018-10-01
      • 1970-01-01
      • 2023-04-09
      • 1970-01-01
      • 1970-01-01
      • 2019-12-13
      • 1970-01-01
      相关资源
      最近更新 更多