Как удалить повторяющиеся строки на основе приоритета и самой высокой конечной даты в MySQL? - PullRequest
2 голосов
/ 23 апреля 2020

У меня есть база данных около 850 тысяч строк данных, в которой есть список клиентов с датами и ссылочными номерами. Данные были собраны с помощью нескольких CSV-файлов, поэтому у меня много повторяющихся данных в базе данных, и сейчас я пытаюсь удалить их на основе набора Правил. Одна вещь, которая, как вы заметите, соответствует в наборе данных, это ссылочный номер, поскольку у каждого клиента будет уникальный номер ссылки, независимо от того, сколько раз его запись была добавлена ​​в базу данных.

У меня есть соберите пример набора данных, чтобы попытаться выяснить, могу ли я построить логи c, и вот мои операторы создания и вставки:

CREATE TABLE `rules_sample` (
 `id` int(11) NOT NULL DEFAULT 0,
 `Name` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
 `Start_Date` date DEFAULT NULL,
 `End_Date` date DEFAULT NULL,
 `Ref_No` mediumtext CHARACTER SET utf8 DEFAULT NULL,
 `Filename` varchar(255) CHARACTER SET utf8 DEFAULT NULL
);


INSERT INTO `rules_sample` (`id`, `Name`, `Start_Date`, `End_Date`, `Ref_No`, `Filename`) VALUES
(172251, 'Mr. Humpty Dumpty', '2018-01-01', '2018-01-30', '110001239', 'Unknown'),
(956757, 'Humpty Dumpty', '2018-02-01', '2019-02-01', '110001239', 'Main 1'),
(957765, 'Humpty Dumpty', '2017-02-01', '2018-02-01', '110001239', 'Main 1'),
(958415, 'Humpty Dumpty', '2016-02-01', '2017-01-31', '110001239', 'Main 1'),
(958635, 'Mr Humpty Dumpty', '2014-11-13', '2015-11-13', '110001239', 'Main 1'),
(1104524, 'Mr. Humpty Dumpty', '2018-01-30', '2017-08-03', '110001239', 'Unknown'),
(1104662, 'Humpty Dumpty', '2018-02-01', '2017-08-05', '110001239', 'Unknown'),
(1114207, 'Humpty Dumpty', '2017-02-01', '2018-02-01', '110001239', 'Unknown'),
(1114504, 'Mr Humpty Dumpty', '2014-11-13', '2015-11-13', '110001239', 'Unknown'),
(1348915, 'Mr. Humpty Dumpty', '2018-01-30', '2019-01-30', '110001239', 'Other_Data'),
(92625, 'Mickey Mouse', '2018-08-09', '2018-08-08', '110003936', 'Unknown'),
(93713, 'Mr&Mrs M Mouse', '2017-06-23', '2019-06-22', '110003936', 'Unknown'),
(94978, 'Mickey Mouse', '2018-08-09', '2020-08-08', '110003936', 'Unknown'),
(847136, 'Mickey Mouse', '2020-08-08', '2020-08-08', '110003936', 'Data'),
(847193, 'Mickey Mouse', '2018-08-08', '2018-08-08', '110003936', 'Data'),
(847379, 'Mr&Mrs M Mouse', '2019-06-22', '2019-06-22', '110003936', 'Data'),
(858126, 'Mr&Mrs M Mouse', '2019-08-08', '2019-08-08', '110003936', 'Data'),
(1288753, 'Mr&Mrs M Mouse', '2018-06-22', '2019-06-22', '110003936', 'ABC Services'),
(930743, '.', '2020-08-14', '2020-08-14', '116000074', 'ABC Services'),
(930980, '.', '2020-07-22', '2020-07-22', '116000074', 'ABC Services'),
(931226, '.', '2020-06-30', '2020-06-30', '116000074', 'ABC Services'),
(931804, '.', '2020-05-13', '2020-05-13', '116000074', 'ABC Services'),
(932008, '.', '2020-05-03', '2020-05-03', '116000074', 'ABC Services'),
(932230, '.', '2020-04-26', '2020-04-26', '116000074', 'ABC Services'),
(932644, '.', '2020-04-10', '2020-04-10', '116000074', 'ABC Services'),
(933416, '.', '2020-03-17', '2020-03-17', '116000074', 'ABC Services'),
(933591, '.', '2020-03-08', '2020-03-08', '116000074', 'ABC Services'),
(933887, '.', '2020-02-27', '2020-02-27', '116000074', 'ABC Services'),
(934965, '.', '2020-01-21', '2020-01-21', '116000074', 'ABC Services');

Теперь мои правила основаны на 2 факторах, 1) 2) список приоритетов на основе имени файла (показано ниже).

Priority | Filename
1 | Main 1
2 | Data
3 | ABC Services
4 | Other_Data
5 | Unknown

Первые шаги, которые я предпринял, - написать следующий код для ранжирования даты окончания:

SELECT 
    T1.*,
    Row_Number() OVER (PARTITION BY Ref_No ORDER BY End_Date DESC) rank
FROM 
    rules_sample T1
    ;

Это дает мне следующий вывод:

id  Name    Start_Date  End_Date    Mpan_MPR    Data_Source rank
956757  Humpty Dumpty   2018-02-01  2019-02-01  110001239   Main 1 1
1348915 Mr. Humpty Dumpty   2018-01-30  2019-01-30  110001239   Other_Data 2
957765  Humpty Dumpty   2017-02-01  2018-02-01  110001239   Main 1 3
1114207 Humpty Dumpty   2017-02-01  2018-02-01  110001239   Unknown 4
172251  Mr. Humpty Dumpty   2018-01-01  2018-01-30  110001239   Unknown 5
1104662 Humpty Dumpty   2018-02-01  2017-08-05  110001239   Unknown 6
1104524 Mr. Humpty Dumpty   2018-01-30  2017-08-03  110001239   Unknown 7
958415  Humpty Dumpty   2016-02-01  2017-01-31  110001239   Main 1 8
958635  Mr Humpty Dumpty    2014-11-13  2015-11-13  110001239   Main 9
1114504 Mr Humpty Dumpty    2014-11-13  2015-11-13  110001239   Unknown 10
94978   Mickey Mouse    2018-08-09  2020-08-08  110003936   Unknown 1
847136  Mickey Mouse    2020-08-08  2020-08-08  110003936   Data 2
858126  Mr&Mrs M Mouse  2019-08-08  2019-08-08  110003936   Data 3
93713   Mr&Mrs M Mouse  2017-06-23  2019-06-22  110003936   Unknown 4
847379  Mr&Mrs M Mouse  2019-06-22  2019-06-22  110003936   Data 5
1288753 Mr&Mrs M Mouse  2018-06-22  2019-06-22  110003936   ABC Services 6
92625   Mickey Mouse    2018-08-09  2018-08-08  110003936   Unknown 7
847193  Mickey Mouse    2018-08-08  2018-08-08  110003936   Data 8
930743  .   2020-08-14  2020-08-14  116000074   ABC Services 1
930980  .   2020-07-22  2020-07-22  116000074   ABC Services 2
931226  .   2020-06-30  2020-06-30  116000074   ABC Services 3
931804  .   2020-05-13  2020-05-13  116000074   ABC Services 4
932008  .   2020-05-03  2020-05-03  116000074   ABC Services 5
932230  .   2020-04-26  2020-04-26  116000074   ABC Services 6
932644  .   2020-04-10  2020-04-10  116000074   ABC Services 7
933416  .   2020-03-17  2020-03-17  116000074   ABC Services 8
933591  .   2020-03-08  2020-03-08  116000074   ABC Services 9
933887  .   2020-02-27  2020-02-27  116000074   ABC Services 10
934965  .   2020-01-21  2020-01-21  116000074   ABC Services 11

Теперь я пытаюсь понять, как включить список приоритетов в мой код. Мой окончательный результат должен выглядеть следующим образом:

id  Name    Start_Date  End_Date    Mpan_MPR    Data_Source
956757  Humpty Dumpty   2018-02-01  2019-02-01  110001239   Main 1
847136  Mickey Mouse    2020-08-08  2020-08-08  110003936   Data
930743  .       2020-08-14  2020-08-14  116000074   ABC Services

Я объясню, как работает мой окончательный результат:

Для 110001239 это довольно просто, End_Date с рангом 1 имеет имя Main 1, которое имеет Приоритет 1 из списка, поэтому остальные данные должны быть удалены.

110003936 немного сложнее, так как самая высокая End_Date имеет имя файла Unknown, но приоритет для этого 5, теперь вторая End_Date - это та же End_Date, что и первая, и имя файла для этого - Data с приоритетом 2, поэтому следует сохранить строку с рангом 2, а остальные удалить.

116000074, это просто, так как ранг 1 End_Date должен быть сохранен, поскольку у нас есть только 1 имя файла во всех записях.

Одна из ключевых вещей, на которые следует обратить внимание, - End_Date переопределяет Приоритет имени файла. Мой код должен учитывать записи, в которых у меня могут быть все имена файлов в одном и том же Ref_No, но это будет go в зависимости от максимальной даты окончания.

Надеюсь, что все имеет смысл.

1 Ответ

0 голосов
/ 23 апреля 2020

Если бы я следовал за вами правильно, вы могли бы использовать строковую функцию field() в качестве второго критерия сортировки в оконной функции:

row_number() over (
    partition by ref_no 
    order by 
        end_date desc, 
        field(filename, 'Main 1', 'Data', 'ABC Services', 'Other_data', 'Unknown')
) rank

field() возвращает индекс первое соответствующее значение в списке - например, если filename имеет значение 'Data', например, оно вернет 2.

Есть небольшая ловушка в том факте, что field() возвращает 0, если значение не соответствует ничего в списке. Если это может произойти, то вы можете отсортировать в обратном порядке:

row_number() over (
    partition by ref_no 
    order by 
        end_date desc, 
        field(filename, 'Unknown', 'Other_data', 'ABC Services', 'Data', 'Main 1') desc
) rank
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...