SQL。根据多个条件删除重复的记录

时间:2018-10-31 15:53:09

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

我有一个叫TABLE的食物,有数千条记录。每个记录都是由描述和5个类别组成的食物。每个后续类别比最后一个类别更为具体。说明,cat1和cat2无法接受NULL值。 Cat3,cat4和cat5可以接受NULL值。

例如:

description | cat1 | cat2    | cat3  | cat4      | cat5
Green apple | Food | produce | NULL  | apple     | NULL
Root beer   | Bev  | Non-Alc | NULL  | Root beer | NULL

我遇到的问题是,有很多重复的描述被分配了不同的类别。而且我需要编写代码来在一定条件下删除这些重复项的帮助。

示例:

description    | cat1 | cat2     | cat3     | cat4  | cat5
Mango Syrup    | Food | Produce  | NULL     | Mango | NULL
Mango Syrup    | Food | Dry Good | NULL     | NULL  | Syrup
Pepperoni Pizza| Food | Meat     | Pepperoni| NULL  | NULL
Pepperoni Pizza| Food | Bakery   | NULL     | Pizza | NULL

我有成百上千个,幸运的是,它们都以相同的方式设置。在cat3、4和5的三列中,只能填充一列。如果记录的cat5 IS NOT NULL,则cat3和cat4将为NULL。如果记录的cat4 IS NOT NULL,则cat3和cat5将为NULL。如果记录的cat3 IS NOT NULL,则cat4和cat5将为NULL

正确的重复项是记录中填充了最具体类别的项目。其他所有重复项都应删除。

我尝试过的事情: GROUP BY,并使用MIN()MAX()汇总不同的类别。这不会给我我想要的结果。

任何事情都会有所帮助。赞赏。

1 个答案:

答案 0 :(得分:1)

因此,对于每个描述,您都希望该行具有“最大”类别。

一种方法使用row_number()

select t.*
from (select t.*,
             row_number() over (partition by description
                                order by case when cat5 is null then 1
                                              when cat4 is null then 2
                                              when cat3 is null then 3
                                              when cat2 is null then 4
                                              when cat1 is null then 5
                                         end
                                ) as seqnum
      from t
     ) t
where seqnum = 1;

如果您实际上要删除其他行,请使用可更新的CTE:

with todelete as (
      select t.*
      from (select t.*,
                   row_number() over (partition by description
                                      order by case when cat5 is null then 1
                                                    when cat4 is null then 2
                                                    when cat3 is null then 3
                                                    when cat2 is null then 4
                                                    when cat1 is null then 5
                                               end
                                      ) as seqnum
            from t
           ) t
      )
delete from todelete
    where seqnum > 1;