- Создайте пустой дубликат таблицы - например,
mytable_to_update
. - Выполните несколько запросов, чтобы найти дубликаты.
- Начните с заполнения вновь созданная таблица с недубликатами. Первоначальный запрос:
SELECT SUBSTRING_INDEX(Name,' ',1),COUNT(*)
FROM mytable_to_update
GROUP BY SUBSTRING_INDEX(Name,' ',1) HAVING COUNT(*) = 1;
SUBSTRING_INDEX захватит первую строку перед пробелом (''). В этом примере Sam Mcarthy
будет заменено только Sam
. Затем используйте это, чтобы сгруппировать и подсчитать, сколько имен у него есть. HAVING COUNT(*) = 1
покажет только одно встречающееся имя. Но это может также ничего не вернуть, если есть такие имена, как Joe
и Joe John
, но на самом деле это два разных человека с разными адресами (поскольку первый запрос группируется только по имени). Следовательно, нам нужно добавить в смесь address
сравнение.
- Добавьте ту же функцию в столбец
Address
следующим образом:
SELECT SUBSTRING_INDEX(Name,' ',1),
SUBSTRING_INDEX(Address,' ',1), /*we take the first string in the address*/
COUNT(*)
FROM mytable_to_update
GROUP BY SUBSTRING_INDEX(Name,' ',1),
SUBSTRING_INDEX(Address,' ',1) /*then add group by for the address*/
HAVING COUNT(*) = 1;
Аналогично, мы берем только первое вхождение строки из адреса. Итак, скажем, например, есть два данных, которые выглядят так, Joe, 12 Street..
и Joe John, 12 St. ..
, что произойдет, если приведенный выше запрос (с учетом функции SUBSTRING_INDEX
) примет только первое вхождение строки; Joe, 12
, который вернет значение счетчика как 2. Это означает, что оба данных (Joe, 12 Street..
и Joe John, 12 St. ..
) считаются дубликатами и не будут отображаться в результатах запроса.
- Измените запрос для перечисления всех недубликатов
ID
для вставки в mytable_to_update
таблицу:
INSERT INTO mytable_to_update
SELECT * FROM mytable WHERE ID IN
(SELECT GROUP_CONCAT(ID) /*replace everything else in the select with just `ID`*/
FROM mytable
GROUP BY SUBSTRING_INDEX(Name,' ',1),
SUBSTRING_INDEX(Address,' ',1)
HAVING COUNT(*) = 1) ;
Примечание: я использую GROUP_CONCAT (ID) из-за несовместимости sql_mode = only_full_group_by - если устанавливается. Конечно, результат может быть другим (например, '1,2' или '1 ,,,,,'), но поскольку мы смотрим только на любое count = 1, проблем быть не должно, так как он вернет только 1 стоимость. Я тестировал ANY_VALUE , он также возвращает аналогичные результаты.
Теперь у вас есть все недубликаты в таблице mytable_to_update
. следующий шаг - поиск дубликатов и вставка только тех, которые вам нужны. Это всего лишь предположение / предположение о том, что вы можете захотеть, и оно не на 100% точно из-за характера сравниваемых данных.
- Запрос аналогичен по структуре и изменяется только в несколько мест, например:
SELECT GROUP_CONCAT(ID), /*add GROUP_CONCAT to list all the duplicates group by the first name & address string.*/
Name,
Address,
COUNT(*)
FROM mytable
GROUP BY SUBSTRING_INDEX(Name,' ',1),
SUBSTRING_INDEX(Address,' ',1)
HAVING COUNT(*) > 1; /*Change '= 1' to '> 1' to get any records with more than 1 count.*/
Использование GROUP_CONCAT для создания списка ID
, разделенного запятыми, который имеет возможные дубликаты.
- Затем добавьте
GROUP_CONCAT
ко всем перечисленным столбцам с идентичными ORDER BY
, чтобы все столбцы были упорядочены по одному и тому же принципу.
SELECT GROUP_CONCAT(ID ORDER BY ID), /*add ORDER BY*/
GROUP_CONCAT(Name ORDER BY ID),
GROUP_CONCAT(Address ORDER BY ID),
COUNT(*)
FROM mytable
GROUP BY SUBSTRING_INDEX(Name,' ',1),
SUBSTRING_INDEX(Address,' ',1)
HAVING COUNT(*) > 1;
С этим вы go над возвращенными значениями для любого из дубликатов и сравните их рядом. Таким образом, вы можете решить опустить любой идентификатор, который не должен отображаться в списке, добавив WHERE ID NOT IN(1,3 ...)
et c.
- После того, как вы окончательно определили, какой
ID
вы хотите чтобы сохранить, вы можете сделать что-то вроде этого:
INSERT INTO mytable_to_update
SELECT * FROM mytable WHERE ID IN
(SELECT SUBSTRING_INDEX(GROUP_CONCAT(ID ORDER BY ID),',',1)
/*assuming that you only want the first ID in the set, do SUBSTRING_INDEX to separate the first ID*/
FROM mytable
GROUP BY SUBSTRING_INDEX(Name,' ',1),
SUBSTRING_INDEX(Address,' ',1)
HAVING COUNT(*) > 1);
Теперь у вас будет таблица (mytable_to_update
), в которой, вероятно, могут быть все не дубликаты. Если некоторые данные в mytable_to_update
не соответствуют вашим требованиям, вы можете просто удалить их или, если есть данные, которые, по вашему мнению, не являются дубликатами, вы можете вставить их. Впоследствии это в значительной степени ручной процесс; ну, даже с запросами, только вы можете определить, верны ли процессы / данные.
Вот скрипка: https://www.db-fiddle.com/f/6Dfrn78mqZbGTwZs3U9Vhi/0