Премахване на дубликати от маса

задача
Вие искате да премахнете дубликати от масата, за да съдържа само уникални записи.

решение
Изберете уникални редове от таблица в друга таблица и да я замените оригиналната. Или добавете уникален индекс на масата и да използват ALTER TABLE, в резултат на дубликати изчезват. Или прилага изтриете. LIMIT н за да се отстранят всички, но едно от копията на дублиращи се редове.

дискусия
При създаване на маса, сте забравили да се определят уникален индекс за предотвратяване на дубликати в таблицата, а след това в бъдеще, можете mozhetestolknutsya с необходимостта да се по някакъв начин да се отървете от дубликати. Таблица cat_mailing от примерите на предишните части се отнася до точно такава маса, тъй като тя съдържа няколко записа на едни и същи хора?

MySQL> SELECT * ОТ cat_mailing РЕД ОТ last_name, first_name;


|
| Бакстър | Уолъс | 57 третата Ave. Apt 102 |
| Браун | Вартоломей | 432 River Run |
| Исаксън | Джим | 515 Fordam Св Ап. 917 |
| Мактавиш | Тейлър | 432 River Run |
| Пинтер | Марлене | 9 Sunset пътека |
| Пинтер | Марлене | 9 Sunset пътека |
+----------+---------------+-----------------------------+

Таблицата съдържа излишни данни, и е добра идея да ги премахнете, за да се избегне повторно разпространение и намаляване на пощенските разходи. Има няколко начина да направите това:

• Изберете уникален ред на таблицата в друга маса, а след това използвайте новата таблица за подмяна на оригинала. В резултат на това дубликати ще бъдат изтрити. Този метод е подходящ, когато дубликат разбрано напълно съответстващи линии.

• Добави в таблицата уникален индекс, като използвате ALTER масата. Тази операция премахва дублиращите се редове въз основа на съдържанието на индексирани колони.

• Дубликати на определен набор от дублиращи се редове могат да бъдат изтрити с помощта на изтриване на оферти.


LIMIT н, изтриване на всички линии с изключение на една.

В този раздел, всички тези методи са разгледани подробно. Мисля си за кой да изберете, при определени условия, не забравяйте, че приложимостта на метода за конкретна задача често се определя от отговорите на два въпроса:

• Трябва ли да има уникален индекс на масата?

• Ако колоната, в която има дубликати, позволява използването на NULL, дали методът ще премахне дублиращите се стойности NULL?

Премахване на дубликат на маса чрез замяна
Един от начините за отстраняване на дубликати от една маса е неговата уникална селекция от записи в новата таблица с една и съща структура. След първоначалния таблицата се заменя с нов. Ако се прецени, линията за предаване на дубликат на друг ред, само ако те са напълно съвпадат, то може да се използва, за да изберете уникални реда SELECT DISTINCT:

MySQL> CREATE TABLE ТМР SELECT DISTINCT * ОТ cat_mailing;
MySQL> SELECT * ОТ ТМР РЕД ОТ last_name, first_name;


|
| Бакстър | Уолъс | 57 третата Ave. Apt 102 |
| Браун | Вартоломей | 432 River Run |
| Исаксън | Джим | 515 Fordam Св Ап. 917 |
| Мактавиш | Тейлър | 432 River Run |
| Пинтер | Марлене | 9 Sunset пътека |
+-----------+--------------+-----------------------------+

Този метод работи при липса на индекса (въпреки че тя може да бъде бавен за големи таблици), но таблиците, които съдържат дублиращи се стойности NULL, то премахва тези дубликати. Имайте предвид, че в този случай, малко по-различни стойности за улично линия Уолъс Бакстър считат за различни.

Ако дубликати се определят само по отношение на подмножество на колони в таблица, създаване на нова таблица, която има уникален индекс, а след това изберете в съответствие с помощта на INSERT игнорирате.

MySQL> CREATE TABLE ТМР (
-> Last_name CHAR (40) NOT NULL,
-> First_name CHAR (40) NOT NULL,
-> Улица CHAR (40) NOT NULL,
-> Първичен ключ (last_name, first_name));
MySQL> INSERT IGNORE В ТМР SELECT * ОТ cat_mailing;
MySQL> SELECT * ОТ ТМР РЕД ОТ last_name, first_name;

Индексът не позволява поставяне на рекорди с дублиращи се стойности в ключов ПТУ, и да се игнорира показва, MySQL, че не трябва да се прекратява с грешка при откриването на дублирани. Недостатъкът е, че ако индексирани колоните могат да съдържат нула стойности, е необходимо да се използва индекс вместо UNIQUE първичен ключ, и след това се отстраняват от дублиращи се ключове нула стойности (уникален индекс позволява няколко стойности NULL).

След създаването на нова таблица ПТУ, съдържащ само отделните редове, използвайте го, за да замени оригиналния таблицата cat_mailing. В резултат на това cat_mailing вече няма да съдържат дубликати:

MySQL> DROP ТАБЛИЦА cat_mailing;
MySQL> ALTER TABLE ПТУ преименувате на cat_mailing;

Премахване на дубликат чрез добавяне на индекса на
За да премахнете дубликати от масата директно "на място", добави в таблицата уникален индекс, като използвате ALTER масата, като се използва за игнориране ключова дума, за да се посочи необходимостта от заличаване на записи с дублиращи се ключови стойности в процеса на изграждане на индекса. Cat_mailing маса източник без индексът е както следва:

MySQL> SELECT * ОТ cat_mailing РЕД ОТ last_name, first_name;

+-----------+------------+-------------------------------+
| last_name | first_name | улица |
+-----------+------------+-------------------------------+
| Бакстър | Уолъс | 57 третата Ave. |
| BAXTER | Уолъс | 57 третата Ave. |
| Бакстър | Уолъс | 57 третата Ave. Apt 102 |
| Браун | Вартоломей | 432 River Run |
| Исаксън | Джим | 515 Fordam Св Ап. 917 |
| Мактавиш | Тейлър | 432 River Run |
| Пинтер | Марлене | 9 Sunset пътека |
| Пинтер | Марлене | 9 Sunset пътека |
+----------+---------------+-----------------------------+

Добави уникален индекс и да видим как това ще се отрази на съдържанието на таблицата:

MySQL> ALTER IGNORE ТАБЛИЦА cat_mailing
-> ADD първичен ключ (last_name, first_name);
MySQL> SELECT * ОТ cat_mailing РЕД ОТ last_name, first_name;

Ако индексирани колони могат да съдържат NULL стойности, вместо индекса на първичен ключ трябва да използвате уникални. Тогава индексът не премахва дублиращите се стойности NULL.

Изтриване на конкретна поредица от дубликати
Започвайки с MySQL 3.22.7 версия, можете да използвате отчета за LIMIT за ограничаване на офертата ИЗТРИЙ на подмножество на редовете, които иначе биха били отстранени. В тази форма, предложението може да се използва за премахване на дублиращи се записи. Да предположим, че имате една маса тон с това съдържание:

Таблицата присъства три синьо (циан) и два пъти - зелено (зелено) и червен (червено). За да премахнете допълнителни копия на всеки цвят, направете:

MySQL> изтрива от т КЪДЕТО цвят = "син" гранични 2;
MySQL> изтрива от т КЪДЕТО цвят = "зелена" ГРАНИЦА 1;
MySQL> изтрива от т КЪДЕТО цвят = "червен" гранични 1;
MySQL> SELECT * от Т;

Рецепция работи при липсата на уникален индекс и премахва дублират NULL стойности. Това е полезно, ако трябва да се премахне дубликати на определен набор от само редове от таблицата. Все пак, ако искате да премахнете много различни набори от дубликати, такава процедура би не искат да извършват ръчно. Процесът може да бъде автоматизирано с помощта на техники за идентифициране на дубликати. В рецептата създадохме make_dup_count_query () функция за генериране на заявка, преброяване на броя на повтарящите се стойности в споменатото множество от колони в таблицата:

под make_dup_count_query
ми ($ tbl_name, @col_name) = @_;
се върне (
"SELECT COUNT (*)". присъединят ( "", @col_name)
. "\ NFROM $ tbl_name"
. "\ NGROUP ОТ". присъединят ( "", @col_name)
. "\ NHAVING COUNT (*)> 1"
);
>

Възможно е да се напише друга функция delete_dups (), в които работят make_dup_count_query (), за да се определи кои таблични стойности се повтарят толкова често. можете да видите колко дубликати трябва да бъдат отстранени от тези данни, като се използва DELETE ... LIMIT н, така че само едно копие на записа остави в таблицата. delete_dups () функция изглежда така:

под delete_dups
ми ($ гръдна, $ tbl_name, @col_name) = @_;
# Създаване и изпълнение на заявката, която намира дублира
ми $ dup_info = $ dbh-> selectall_arrayref (
make_dup_count_query ($ tbl_name, @col_name)
);
върне ако не е определено ($ dup_info);
# За всеки повтаря набор от ценности, за да изтриете всички срещания на низове,
# Съдържащ стойности, но едно
foreach ми $ row_ref (@)
ми ($ брой, @col_val) = @;
Следващата освен ако $ брои> 1;
# Изграждане на поредица от условия за сравнение ценности, като не се забравя е нула
ми $ ул;
за ($ ми I = 0; $ аз цитираме ($ col_val [$ Ь])
. "$ COL_NAME [$ Ь] е нула";
>
$ Ул = "Изтриване от $ tbl_name КЪДЕ ул $ LIMIT". ($ Граф - 1);
$ Dbh-> направи ($ ул);
>
>

Да предположим, че имаме една маса служител със следните данни:

MySQL> SELECT * FROM служител;

+-----------+--------------+
| име | отдел |
+-----------+--------------+
| Фред | счетоводство |
| Фред | счетоводство |
| Фред | счетоводство |
| Фред | счетоводство |
| Боб | корабоплаване |
| Мери Ан | корабоплаване |
| Мери Ан | корабоплаване |
| Мери Ан | продажби |
| Мери Ан | продажби |
| Мери Ан | продажби |
| Мери Ан | продажби |
| Мери Ан | продажби |
| Мери Ан | продажби |
| Борис | NULL |
| Борис | NULL |
+-----------+-------------+

За да използвате delete_dups () за премахване на дублиращи се колони в таблицата служител на име и отдел, го наричат ​​по този начин:

delete_dups ($ гръдна, "служител", "име", "отдел");

delete_dups () функция призовава make_dup_count_query (функция) и изпълнява това генерира SELECT заявка. За масата за служител, тази заявка показва следния резултат:

delete_dups () функция използва тази информация, за да се образува следните предложения за изтриване:

Изтрий от служител
КЪДЕ име = "Борис" и универсален е нула LIMIT 1
Изтрий от служител
КЪДЕ име = "Фред, универсални = 'счетоводство' LIMIT 3
Изтрий от служител
КЪДЕ име = "Мери Ан, универсални = 'продажби' LIMIT 5
Изтрий от служител
КЪДЕ име = "Мери Ан, универсални = 'доставка' LIMIT 1

Като цяло, метод, използващ DELETE. LIMIT н, вероятно по-бавно от премахване на дублиращи се чрез създаване на втора таблица или да добавите уникален индекс. Тези методи се съхраняват данни на сървъра и му позволяват да извършва цялата работа. Изтриете. LIMIT н изисква голямо количество на клиентските взаимодействия със сървъра, тъй като използва SELECT заявка за извличане на информация за дубликат, а след това редица предложения Изтриване за изтриване на дублиращи се копия редове.