Уроки SQL — как найти повторяющиеся записи (дубли) в базе данных

Во-первых, чтобы не допустить подобных ситуаций, вам заранее нужно присваивать уникальные значения в таблицах. Так вы сможете избежать дублирования записей (строк). Однако, не все в этом мире идеально, и рано или поздно вы можете обнаружить дублирующие строки в своей базе данных: из-за банальной человеческой ошибки, ошибок в коде приложений, неверно обработанных данных, нашествия инопланетян.

Это можно исправить? Да, и в сегодняшнем практическом уроке мы рассмотрим методы нахождения дублирующих данных и борьбы с ними.

 

Что вам потребуется:

  • Доступ к базе данных. Можно через командную строку, но лучше использовать инструмент администрирования с графическим интерфейсом: например, HeidiSQL, phpMyAdmin, Adminer и т.п.
  • Уметь писать SQL-запросы. Ну, или уметь копировать/вставлять код.

 

Что будем искать (критерий нежелательной копии записи)

Сначала определимся, что имеется ввиду под понятием дублирующей строки. Например, в своей практике я столкнулся с тем, что при работе с одним популярным плагином для SEO продвижения в WordPress создается много повторяющихся записей в базе данных. Речь идет о записях мета-данных title, description и keywords для публикаций в блоге. Они записываются в таблицу wp_postmeta и еще отдельно в таблицу плагина wp_aioseo_posts. Когда мне нужно было сделать общую выборку из этих двух таблиц, я обратил внимание на то, что для некоторых постов данные содержатся в разных строках. То есть, для одного поста с уникальным значением post_id было несколько различных (нежелательных) строк. Возможно, это произошло после обновления плагина, и разработчики сменили название ключа для поля мета-данных с _aioseo_ на _aioseop_ (фактически добавив одну букву)? Скорее всего. И в результате база данных обогатилась на дубликаты. У вас может быть и другая ситуация, но решение в данном уроке может быть вполне применимо и к ней.

Итак, теперь перейдем от теории к практике.

 

Соединяем данные из двух SQL таблиц

Для начала напишем SQL-запрос, который делает выборку из двух таблиц базы данных и записывает результаты в новую (существующую) таблицу new_table:

INSERT INTO `new_table`(`post_id`, `title`, `description`, `keywords`, `seo_title`)
SELECT aio.post_id, title, description, keywords, wp.meta_value
FROM wp_aioseo_posts AS aio
LEFT JOIN wp_postmeta AS wp
ON wp.post_id = aio.post_id
AND wp.meta_key = '_aioseop_title'
ORDER BY post_id;

 

Если у вас возникают трудности на этапе выборки из двух и более таблиц, рекомендую ознакомиться с тематическим уроком Знакомство с операторами INNER, LEFT, RIGHT, SELF и CROSS JOIN.

 

Этот запрос работает, и мы получаем данные из двух таблиц. В примерно таком виде:

+---------+----------------+------------------+----------+--------------------+
| post_id | title          | description      | keywords | meta_value         |
+---------+----------------+------------------+----------+--------------------+
|      1  | Blah-blah-blah | Blah, blah, blah | blah     | blah – blah – blah |
|      2  | Blah-blah-blah | Blah, blah, blah | blah     | blah – blah – blah |
|      3  | Blah-blah-blah | Blah, blah, blah | blah     | blah – blah – blah |
+---------+----------------+------------------+----------+--------------------+

 

Но что, если расширить выборку? Ведь meta_key в таблице wp_postmeta может иметь значение и _aioseo_title, и _aioseop_title? Тогда в новую таблицу запишутся дубликаты. И теперь пришла пора отыскать эти дублирующиеся данные.

 

Как с помощью SQL запроса найти все строки, которые содержат дубликаты?

Для этого вы можете использовать функцию COUNT(column_name) и выражение GROUP BY.

В моем примере: я хочу найти и сгруппировать данные по столбцам post_id и seo_title, а также получить количество полученных дублей.

Вот такой будет SQL запрос:

SELECT post_id, seo_title, COUNT(*)
FROM new_table
GROUP BY post_id, seo_title
HAVING COUNT(*) > 1

 

Результатом будет нечто подобное:

+---------+------------------------------------------+----------+
| post_id | seo_title                                | COUNT(*) |
+---------+------------------------------------------+----------+
|     514 | Легендарному сериалу Друзья — 20 лет!    |        2 |
|     514 | NULL                                     |        2 |
|     903 | Как добавить свой сайт в Google Maps     |        2 |
|     903 | NULL                                     |        2 |
=================================================================
+---------+------------------------------------------+----------+
44 rows in set (0.01 sec)

 

Как видно из результата, в таблице есть дубликаты (и их может быть немало), а в отдельной колонке COUNT(*) указано их количество. Я показал только часть результатов, но что делать, если таких повторяющихся данных тысячи?

 

Что можно сделать с повторяющимися данными в SQL таблице?

Простейший способ — это игнорировать дубликаты с помощью ключевого слова DISTINCT, которое нужно добавить в функцию COUNT(). Например, так:

SELECT post_id, seo_title, COUNT(DISTINCT seo_title)
FROM new_table
GROUP BY post_id

 

Ключевое слово DISTINCT позволяет игнорировать повторяющиеся данные, и выбирать только уникальные. В результате я получил список уникальных данных, без повторяющихся строк. Примечательно, что вполне вероятно и возможны дубликаты, которые не являются ошибочными. Например, в моей базе данных есть повторяющиеся заголовки у постов с типом Цитата, ведь у одного автора может быть и не одна цитата, а seo_title при этом может быть одинаков. И это не будет ошибкой. Поэтому, я и добавил группировку по полю post_id, которое должно быть уникальным. Обращайте и на такие нюансы внимание.

 

Recent Posts

Конфуций

То, что вы воспринимаете спокойно, больше не управляет вами Конфуций  

18 часов ago

Каждый ли застройщик осилит строительство таунхаусов?

Многие застройщики считают таунхаусы идеальным балансом при решении проблемы доступности жилья, плотности застройки и тех…

1 день ago

Ультрафильтрация: современное решение для очистки питьевой воды

Чистая питьевая вода – это залог здоровья и хорошего самочувствия. Водопроводная вода даже после централизованной…

4 дня ago

Онлайн-обучение и традиционное образование: как найти свой формат

Образование уже давно перестало быть только о лекциях в аудиториях и толстых конспектах. Сейчас любая…

4 недели ago

Афилейт маркетинг обучение: От старта к успеху в цифровом бизнесе

В современном цифровом мире афилейт маркетинг стал одним из наиболее популярных способов монетизации трафика и…

4 недели ago

Джек Лондон

Вместо того, чтобы стирать слезы с лица, стирайте из жизни людей, которые заставили вас плакать…

1 месяц ago