即使某些列可能为NULL,也从数据库中删除多个重复的行

问题描述

我继承了一个数据库,该数据库包含一个表,由于缺少唯一的主键,该表具有大量重复项。可悲的是,在添加主键之前,我需要删除除1以外的所有重复项。

所以我在这里找到了很多很棒的答案,并遵循了我阅读的所有建议。

这是我最后遇到的查询

WITH cte
     AS (SELECT ROW_NUMBER() OVER (PARTITION BY storyId,storyDescription,genreId,authorId,submissionDate,submittedBy,submissionUrl 
                                       ORDER BY ( SELECT 0)) RN
         FROM   storyList)
DELETE FROM cte
WHERE  RN > 1;

它确实删除了90%的重复条目。但是,它不会删除某些列中包含NULL值的行。

我很高兴地在其他答案和评论搜索了类似的问题,但找不到与潜在NULL值有关的任何问题。

有没有一种删除其余重复条目的方法,即使它们的某些列可能包含NULL值?

谢谢

解决方法

分别删除它们:

delete from storylist
    where storyId is null or storyDescription is null  or genreId is null or . . . 

但是,这似乎很奇怪。为什么storyid不是候选主键?您打算使用所有列吗?

编辑:

我认为您想保留storyid作为主要内容,并在其他列中优先考虑非null值。如果是这样:

WITH cte as (
      SELECT ROW_NUMBER() OVER (PARTITION BY storyId 
                                    ORDER BY ( (CASE WHEN storyDescription IS NOT NULL THEN 1 ELSE 0 END) +
                                               (CASE WHEN genreId IS NOT NULL THEN 1 ELSE 0 END) +
                                               . . .
                                             ) DESC
                          ) as seqnum
      FROM storyList
     )
DELETE FROM cte
WHERE seqnum > 1;
,

这个时间太长,无法发表评论。这样吧。

如果我正确理解,则以下代码演示了您要尝试执行的操作。我还是没收到,还是可以张贴minimal,reproducible example来说明问题? (也许是SQLFiddle。)

-- Sample data.
declare @Samples as Table ( SampleId Int Identity,SomeString VarChar(16),SomeInt Int );
insert into @Samples ( SomeString,SomeInt ) values
  ( 'foo',3 ),( 'foo',9 ),null ),( 'bar',6 ),( null,null );
select SampleId,SomeString,SomeInt
  from @Samples
  order by SampleId;

-- Get row numbers just to show they are calculated correctly.
select SampleId,SomeInt,Row_Number() over ( partition by SomeString,SomeInt order by SampleId ) as RN
  from @Samples
  order by SomeString,RN;

-- Delete duplicates.
with NumberedRows as (
  select -- SampleId,SomeInt order by SampleId ) as RN
    from @Samples )
  delete from NumberedRows
    where RN > 1;
  
-- Display the remainder.
select SampleId,SomeInt
  from @Samples
  order by SampleId;