2010-02-01 4 views
2

У меня есть таблица, как этотУдаление дублей в MySQL

userid visitorid time 
1  10   2009-12-23 
1  18   2009-12-06 
1  18   2009-12-14 
1  18   2009-12-18 
1705 1678  2010-01-24 
1705 1699  2010-01-24 
1705 1700  2010-01-24 
1712 1   2010-01-25 
1712 640   2010-01-24 
1712 925   2010-01-25 
1712 1600  2010-01-24 
1712 1630  2010-01-25 
1712 1630  2010-01-24 
1713 1   2010-01-24 
1713 1   2010-01-23 

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

Пример, после запроса таблица должна быть, как это

userid visitorid time 
1  10   2009-12-23 
1  18   2009-12-18 
1705 1678  2010-01-24 
1705 1699  2010-01-24 
1705 1700  2010-01-24 
1712 1   2010-01-25 
1712 640   2010-01-24 
1712 925   2010-01-25 
1712 1600  2010-01-24 
1712 1630  2010-01-25 
1713 1   2010-01-24 

ответ

4
Delete from YourTable VersionA 
    where VersionA.Time NOT IN 
    (select MAX(VersionB.Time) Time 
     from YourTable VersionB 
     where VersionA.UserID = VersionB.UserID 
      and VersionA.VisitorID = VersionB.VisitorID) 

Синтаксис может потребоваться корректировка, но СЛЕДУЕТ сделать трюк. Кроме того, вы можете предварительно запросить Subselect в свою собственную таблицу FIRST, а затем запустить DELETE FROM против этого набора результатов.

+0

# 1064 - У вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии сервера MySQL, для правильного синтаксиса для использования рядом с «VersionA», где VersionA.Time NOT IN (выберите MAX (VersionB.Time) Time »в строке 1 –

+0

, можно получить уникальные строки, пренебрегая полем времени затем удалите все остальные строки, кроме тех, и используйте максимальное поле времени? –

+0

«В настоящее время вы не можете удалить из таблицы и выбрать из той же таблицы в подзапросе». http://dev.mysql.com/doc/refman/5.0 /en/delete.html - Это потому, что таблица не заблокирована правильно, и никто не реализовал код, чтобы заблокировать ее правильно. –

0

Предполагая, что ваш стол называется Visitors:

DELETE v1.* FROM Visitors v1 
LEFT JOIN (
    SELECT userid, visitorid, MAX(time) AS time 
    FROM Visitors v2 
    GROUP BY userid, visitorid 
) v3 ON v1.userid=v3.userid AND v1.visitorid=v3.visitorid AND v1.time = v3.time 
WHERE v3.userid IS NULL; 
0
DELETE mo.* 
FROM (
     SELECT userid, visitorid, MAX(time) AS mtime 
     FROM mytable 
     GROUP BY 
       userid, visitorid 
     ) mi 
JOIN mytable mo 
ON  mo.userid = mi.userid 
     AND mo.visitorid = mo.visitorid 
     AND mo.time < mi.mtime 
+0

спасибо, но это удаляет все строки, за исключением только одного ... i.e для последней строки для каждого пользователя остается. –

0

Вы должны работать вокруг MySQL bug#6980 с двойным вложенным подзапросом:

DELETE FROM foo_table 
WHERE foo_table.time IN (
    SELECT time FROM (
     SELECT time FROM 
      foo_table 
      LEFT OUTER JOIN (
       SELECT MAX(time) AS time 
       FROM foo_table 
       GROUP BY userid, visitorid 
       ) AS foo_table_keep 
        USING (time) 
     WHERE 
      foo_table_keep.time IS NULL 
     ) AS foo_table_delete 
    ); 

Использования GROUP BY коллапсирует дубликаты до одной строки, и MAX(time), выбираешь, какое значение вы хотите. Используйте другую агрегированную функцию, чем MAX, если хотите.

Обертывание подзапроса дважды, обеспечивая псевдонимы для каждого, позволяет избежать ошибок:

ERROR 1093 (HY000): You can't specify target table 'foo_table' for update in FROM clause 

и имеет дополнительное преимущество, что это ясно, как оператор выбирает, что сохранить.

Смежные вопросы