Удаление дублирующихся строк внешнего ключа в базе данных MySQL - PullRequest
2 голосов
/ 13 ноября 2011

У меня есть таблица Stores и таблица Schools. Это отношения один ко многим - несколько школ могут обслуживаться одним магазином, но не наоборот.

Ранее в процессе разработки я допустил ошибку, повторяя одно и то же хранилище несколько раз в базе данных Stores. Я вставил строки, как:

Store_ID| Store_URL
1       | http://sameurl.com
2       | http://sameurl.com

И потом, если бы две разные школы были в одном и том же магазине, я бы сослался на 1 в одном школьном ряду и 2 в другом.

Я могу легко идентифицировать дубликаты, используя GROUP BY на Store_URL и используя COUNT() для идентификации дубликатов.

Трудная задача, стоящая передо мной, состоит в том, чтобы все пункты Schools были не дублированы Stores. Если я просто удалю дубликат Stores, у меня будет Schools, указывающий на несуществующие строки.

Что я могу сделать, чтобы устранить дубликаты и сделать так, чтобы школы с одним магазином указывали на одну и ту же строку Store?

Примечание: есть тысячи школ и магазинов. Ручные решения не работают.

Ответы [ 2 ]

6 голосов
/ 13 ноября 2011

Предполагая, что у вашей таблицы School есть store_ID из того, что вы сказали.

Я бы начал с определения каждого дубликата, который store_ID вы хотите сохранить.Я также предполагаю, что вы хотите, чтобы это было самое низкое значение идентификатора.Затем я обновил бы School s 'store_ID, чтобы он стал MIN(store_ID) для текущего URL, который у них есть.После этого вы можете свободно удалять store_ID записей

. Вот как я бы поступил с обновлением:

UPDATE sch
SET sch.Store_ID = matcher.store_ID
FROM Schools AS sch
INNER JOIN Stores AS st ON sch.store_ID = st.store_ID
INNER JOIN
(
   SELECT MIN(st.store_id) AS store_ID, store_url
   FROM Schools AS sch
   INNER JOIN Stores AS st ON sch.store_ID = st.store_ID
   GROUP BY Store_URL
) AS matcher ON st.Store_URL = matcher.Store_Url
   AND st.Store_ID != matcher.store_ID

Если вы можете удалить магазины, у которых нетв связанной школе следующий запрос удалит лишние строки:

DELETE FROM st
FROM Stores AS st
LEFT JOIN Schools AS sch ON st.Store_ID = sch.Store_Id
WHERE sch.Store_id IS NULL

Если вы хотите удалить только дубликаты хранилища, я бы посмотрел на этот запрос вместо приведенного выше:

DELETE FROM st
FROM Stores AS st
INNER JOIN
(
   SELECT MIN(st.store_ID) store_Id, st.Store_Url
   FROM Stores AS st
   GROUP BY st.Store_URL
) AS useful ON st.Store_Url = useful.Store_URL
WHERE st.Store_ID != useful.store_Id
0 голосов
/ 13 ноября 2011

Следующий оператор обновления изменит значения в базе данных одной школы:

UPDATE Schools SET store_id = 1 WHERE store_id = 2;
DELETE FROM Stores WHERE Store_ID = 2;
...