Пометить дубли в MySql таблице

Все делается одним запросом:
Код:
UPDATE `test` SET `is_dubl` = 1 WHERE `url` IN(SELECT `url` FROM (SELECT * FROM `test` GROUP BY `url` HAVING (COUNT(`url`) > 1)) AS `temp`)
вопрос про подзапрос:
(SELECT `url` FROM (SELECT * FROM `test` GROUP BY `url` HAVING (COUNT(`url`) > 1)) AS `temp`)
он принципиально должен быть именно таким (избыточным) или его можно сократить без проблем до:
(SELECT `url` FROM `test` GROUP BY `url` HAVING (COUNT(`url`) > 1)

по поводу поста от trooll
нельзя ли каким нить образом создавать некие временные статические таблицы в памяти ?
 
Не смотря на предупреждения, все таки мне удалось удалить дубли в один запрос. Не знаю может быть у когото работать не будет но у меня все отлично срабатывает.

Решение:
PHP:
DELETE FROM `item` WHERE `id` NOT IN(SELECT * FROM (SELECT MIN(`id`) FROM `item` GROUP BY `h_all` ) AS `temp`)


Просто решил побаловаться с запросами по выше предложенному решению, для обновления записей дублей в базе, взял запрос предложенный saen и чуток переделал его под свои нужды.

Буду очень признателен если кто из гуру MySQL или просто знающих людей, объяснит на пальцах что делает условие в моем решении:
PHP:
SELECT * FROM (*************) AS `temp`
и почему без этого дополнительного подзапроса, не срабатывало удаление дублей?
 
надеюсь гуру нам ответят, а пока давайте сами поэкспериментируем немного с этим подзапросом:

прокатывает ли у вас удаление с подзапросом вида:
(SELECT * FROM (SELECT MIN(`id`) FROM `item` GROUP BY `h_all`))
?
[так можно отсечь вопрос о значимости AS `temp`]

а с таким:
(SELECT MIN(`id`) FROM `item` GROUP BY `h_all` AS `temp`)
 
надеюсь гуру нам ответят, а пока давайте сами поэкспериментируем немного с этим подзапросом:
прокатывает ли у вас удаление с подзапросом вида:
(SELECT * FROM (SELECT MIN(`id`) FROM `item` GROUP BY `h_all`))
?
[так можно отсечь вопрос о значимости AS `temp`]
а с таким:
(SELECT MIN(`id`) FROM `item` GROUP BY `h_all` AS `temp`)

PHP:
(SELECT * FROM (SELECT MIN(`id`) FROM `item` GROUP BY `h_all`))
Возвращает:
1248:Every derived table must have its own alias

PHP:
(SELECT MIN(`id`) FROM `item` GROUP BY `h_all` AS `temp`)
Возвращает:
1064:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS `temp`)' at line 1

Короче что то здесь не то и без бутылки не разберешься:D

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

Во втором запросе синтаксическая ошибка составления запроса, может быть не правильная последовательность или вообще может такая структура не верна...
 
PHP:
(SELECT * FROM (SELECT MIN(`id`) FROM `item` GROUP BY `h_all`))
Возвращает:
1248:Every derived table must have its own alias
PHP:
(SELECT MIN(`id`) FROM `item` GROUP BY `h_all` AS `temp`)
Возвращает:
1064:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS `temp`)' at line 1
Короче что то здесь не то и без бутылки не разберешься:D
В первом запросе требует дать псевдоним, видимо что бы путаницы не было при обработки вложенных запросов.
Во втором запросе синтаксическая ошибка составления запроса, может быть не правильная последовательность или вообще может такая структура не верна...
с этими 2-мя ошибками разобрался

=>
Subqueries are legal in a SELECT statement's FROM clause. The actual syntax is:
SELECT ... FROM (subquery) [AS] name ...
The [AS] name clause is mandatory, because every table in a FROM clause must have a name.
жирным выделена причина 1-й ошибки,
а синим причина второй ошибки [ SELECT MIN(`id`) FROM `item` GROUP BY `h_all` AS `temp` не попадает под шаблон ]

короче, похоже в mysql конструкция вида
(select 'columnName' from (select 'columnName' from ...) as 'tmpName')
является простым подзапросом, который вычисляется лишь один раз в отличии от коррелированного подзапроса, который вычисляется для каждой строки "родительского" запроса. так что эту конструкцию надо/можно использовать в update/delete если в их условии используются ссылки на таблицу над которой производится update/delete.

p.s. в приведенной ссылке есть описание работы с EXPLAIN SELECT - удобная штука смотреть каким именно образом вычисляются подзапросы.
 
Тоже похожая проблема.
Нужно удалить записи из таблицы, у которых 2 поля одинаковые.
Поля code и name, если у 2ух строк оба этих поля совпадают то удалять, если совпадает лишь одно поле, то оставляем.
Подскажите плз как реализовать.
 
Тоже похожая проблема.
Нужно удалить записи из таблицы, у которых 2 поля одинаковые.
Поля code и name, если у 2ух строк оба этих поля совпадают то удалять, если совпадает лишь одно поле, то оставляем.
Подскажите плз как реализовать.
PHP:
UPDATE tableName SET testField='+' WHERE id IN
(#ПЯТЫЙ ЗАПРОС. Получаем копию четвертого запроса, но в "статичном виде" 
SELECT id FROM
 (
 #ЧЕТВЕРТЫЙ ЗАПРОС. Получем id строк, у которых в таблице есть дубли Xgroup
 SELECT id 
 FROM tableName
 WHERE CONCAT('code=', code , 'name=', name) IN 
   (# ТРЕТИЙ ЗАПРОС. Выбираем Xgroup, которые встечаются в исходной таблице более одного раза.
    SELECT Xgroup 
    FROM 
       (# ВТОРОЙ ЗАПРОС. Получем таблицу: [счетчик повторений], строка Xgroup 
        SELECT COUNT(id) AS cnt, Xgroup 
        FROM
            (# ПЕРВЫЙ ЗАПРОС. Выбираем id и [соединенные в одну строку 2 поля] AS Xgroup 
             SELECT id, CONCAT('code=', code , 'name=', name) AS Xgroup 
             FROM tableName
            ) AS ss1 
        GROUP BY Xgroup
        ) AS ss2 
    WHERE cnt > 1
   )
 ) AS ss4
)
протестил у себя на update
для delete замените 1-ю строку на
DELETE FROM tableName WHERE id IN
 
Ладно с двумя полями, как бы по одному полю удалить корректно.
Делаю запрос:
PHP:
SELECT name, COUNT(name) AS cnt
FROM tablename GROUP BY name
HAVING ( COUNT(name) > 1 )

Он выводит количество дублей.

Удаляю так:
PHP:
DELETE t1 FROM tablename t1, tablename t2 WHERE t1.name=t2.name AND t1.ID > t2.ID

Но удаляется раза в 3 больше записей чем находится предыдущим запросом.

Такой способ вообще эффекта не дает:
PHP:
ALTER IGNORE TABLE tablename ADD UNIQUE INDEX(name);

Подскажите как правильно удалить дубли по одному полю...
 
если опять надо удалить все записи у которых есть дубли в поле name, то тот же запрос, что и выше, только заменить в 2-х местах
CONCAT('code=', code , 'name=', name)
на
CONCAT('name=', name)

а если вы хотите удалить только дубли и оставить из всех дублей только одну запись то так и пишите.
 
если опять надо удалить все записи у которых есть дубли в поле name, то тот же запрос, что и выше, только заменить в 2-х местах
CONCAT('code=', code , 'name=', name)
на
CONCAT('name=', name)
а если вы хотите удалить только дубли и оставить из всех дублей только одну запись то так и пишите.
Да, хочу оставить одну запись. Иначе говоря оставить только уникальные записи в таблице.
 
Назад
Сверху