SQL. Удалить дубликаты записей на основе нескольких критериев - PullRequest
0 голосов
/ 31 октября 2018

У меня есть TABLE под названием Food с несколькими тысячами записей. Каждая запись - это еда, состоящая из описания и 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 голосов
/ 31 октября 2018

Таким образом, для каждого описания вы хотите, чтобы строка с «самой большой» категорией была заполнена.

Один метод использует 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...