Форумы портала PHP.SU » PHP » SQL и Архитектура БД » Как удалить одинаковые записи в таблице MySQL

Страниц (1): [1]
 

1. AlexGreF - 25 Апреля, 2010 - 17:17:04 - перейти к сообщению
У меня такая задача:
Есть таблица MySQL, например такая:
CODE (SQL):
скопировать код в буфер обмена
  1. CREATE TABLE IF NOT EXISTS `table` (
  2.   `id` int(11) NOT NULL AUTO_INCREMENT,
  3.   `name` varchar(255) DEFAULT NULL,
  4.   `price` int(11) NOT NULL DEFAULT '0',
  5.   `year` int(11) NOT NULL DEFAULT '1901',
  6.   `probeg` int(11) NOT NULL DEFAULT '0',
  7.   `description` varchar(10000) DEFAULT NULL,
  8.   `city` varchar(255) DEFAULT NULL,
  9.   `phone` varchar(255) NOT NULL DEFAULT '0',
  10.   PRIMARY KEY  (`id`)
  11. ) ENGINE=MyISAM  DEFAULT CHARSET=cp1251;


В таблице более 30 000 строк. Нужно удалить строки с одинаковыми значениями по полям `name`,`year`,`price`,`probeg` и `city`. Причём удалять не все, а последнюю оставлять(ну то есть убрать одинаковые, а оригинал оставить).

Я попробовал сделать так :
PHP:
скопировать код в буфер обмена
  1. $sql = "SELECT `id`,`name`,`price`,`year`,`probeg`,`city` FROM `table`";
  2. $result = mysql_query($sql);
  3. while($ad = mysql_fetch_array($result)){
  4.         $sql = "SELECT `id` FROM `table` WHERE `name`='".$ad['name']."' AND `price`=".$ad['price']." AND `year`=".$ad['year']." AND `probeg`=".$ad['probeg']." AND `city`='".$ad['city']."' AND `id`!=".$ad['id'];
  5.         $rows = @mysql_num_rows(mysql_query($sql));
  6.         if($rows>0){
  7.                 $sames = mysql_query($sql);
  8.                 while($ads = mysql_fetch_array($sames)){
  9.                         echo $ads['id'].'<br>';
  10.                 }
  11.                 echo 'Исходный - <B>'.$ad['id'].'</B><hr>';
  12.         }
  13. }
  14.  


Этот код по идее должен вывести одинаковые строки(`id` строк), но видать памяти не хватает наверно(более 30тыс. строк в таблице), выводит "HTTP-шлюз не отвечает (код ошибки: 504)"
2. Champion - 25 Апреля, 2010 - 17:24:56 - перейти к сообщению
CODE (SQL):
скопировать код в буфер обмена
  1. DELETE FROM tbl t1 WHERE EXISTS (SELECT * FROM tbl t2 WHERE t1.name = t2.name /* и остальное кроме id */ AND t1.id < t2.id)

(Добавление)
Перед удалением делай селект того же самого, что в него попадает точно то, что нужно
3. AlexGreF - 25 Апреля, 2010 - 19:16:04 - перейти к сообщению
Champion пишет:
CODE (SQL):
скопировать код в буфер обмена
  1. DELETE FROM tbl t1 WHERE EXISTS (SELECT * FROM tbl t2 WHERE t1.name = t2.name /* и остальное кроме id */ AND t1.id < t2.id)

А вто такой запрос тоже должен работать? :
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT *
  2. FROM tbl t1
  3. WHERE EXISTS (
  4.  
  5. SELECT *
  6. FROM tbl t2
  7. WHERE t1.name = t2.name
  8. AND t1.id < t2.id
  9. )
  10. LIMIT 0 , 30

Попробовал такой запрос - та же ошибка, в самом phpMyAdmin - шлюз не отвечает(после долгого раздумывания)
Champion пишет:
Перед удалением делай селект того же самого, что в него попадает точно то, что нужно

Вот это что то не понял..
4. Champion - 25 Апреля, 2010 - 20:20:52 - перейти к сообщению
Да, такой запрос должен работать. Ну если таблицу настоящую указать и поля.
А долгое раздумье может быть из-за того, что таблица большая, а индексов нет по нужным полям. В результате приходится на каждую запись проходиться фулл-сканом по всей таблице целиком.
Создай составной индекс по всем полям, по которым сравниваешь, будет быстрее.
5. AlexGreF - 26 Апреля, 2010 - 04:23:58 - перейти к сообщению
Champion пишет:
Создай составной индекс по всем полям, по которым сравниваешь, будет быстрее.

Если не трудно объясни поподробнее? А то я в MySQL как то не очень в таких тонкостях..
6. Champion - 26 Апреля, 2010 - 12:53:15 - перейти к сообщению
CREATE INDEX idx1ef3hxxhfec4de ON tbl (filed1, filed2, filed3, dield4, field5,field6)

 

Powered by ExBB FM 1.0 RC1