По-перше, щоб не допустити подібних ситуацій, вам заздалегідь потрібно надавати унікальні значення у таблицях. Так ви зможете уникнути дублювання записів (рядків). Однак, не все в цьому світі ідеально, і рано чи пізно ви можете виявити дублюючі рядки у своїй базі даних: через банальну людську помилку, помилки в коді додатків, неправильно оброблені дані, нашестя інопланетян.
Чи можна це виправити? Так, і в сьогоднішньому практичному уроці ми розглянемо методи знаходження дубльованих даних та боротьби з ними.
Що вам знадобиться:
Спочатку визначимося, що мається на увазі під поняттям дублюючого рядка. Наприклад, у своїй практиці я зіткнувся з тим, що при роботі з одним популярним плагіном для SEO просування в WordPress створюється багато записів в базі даних, що повторюються. Йдеться про записи мета-даних title
, description
та keywords
для публікацій у блозі. Вони записуються в таблицю wp_postmeta
і окремо в таблицю плагіну wp_aioseo_posts
. Коли мені потрібно було зробити загальну вибірку з цих двох таблиць, я звернув увагу на те, що для деяких постів дані містяться у різних рядках. Тобто для одного посту з унікальним значенням post_id
було кілька різних (небажаних) рядків. Можливо, це сталося після оновлення плагіна, і розробники змінили назву ключа для поля мета-даних з _aioseo_
на _aioseop_
(фактично додавши одну літеру)? Швидше за все. І в результаті база даних збагатилася на дублікати. У вас може бути й інша ситуація, але рішення в даному уроці може бути цілком застосовним і до неї.
Отже, тепер перейдемо від теорії до практики.
Для початку напишемо 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
? Тоді до нової таблиці запишуться дублікати. І тепер настав час знайти ці дублюючі дані.
Для цього можна використовувати функцію 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(*)
показано їх кількість. Я навів у прикладі лише частину результатів, але що робити, якщо таких повторюваних даних тисячі?
Найпростіший спосіб — це ігнорувати дублікати за допомоги ключового слова DISTINCT
, яке потрібно додати до функції COUNT()
. Наприклад, так:
SELECT post_id, seo_title, COUNT(DISTINCT seo_title) FROM new_table GROUP BY post_id
Ключове слово DISTINCT
дозволяє ігнорувати дані, що повторюються, і вибирати тільки унікальні. В результаті я отримав список унікальних даних, без рядків, що повторюються. Примітно, що цілком ймовірно і можливі дублікати, які не є помилковими. Наприклад, у моїй базі даних є заголовки у постів з типом Цитата, що повторюються, адже в одного автора може бути і не одна цитата, а seo_title
при цьому може бути однаковий. І це не буде помилкою. Тому я додав групування по полю post_id
, яке має бути унікальним. Звертайте і на такі нюанси увагу.
Якщо хочеш пізнати людину, не слухай, що про неї говорять інші, послухай, що вона говорить…
Вибачення — не означає, що ти не правий, а інша людина має рацію. Це всього…
Атмосферу паперової книги, запах свіжого чорнила і паперу, що трохи залежався, складно замінити гаджетами. Але…