[SQL] Из вопросов на собеседовании: как удалить дубликаты?
а в чем проблема?
Проблемы нет, были несколько решений. Какое круче?
так это. тут разные "если" есть. а стандартное наваять не факт оптимальное проблем нет.
приведи хоть варианты. интересно
приведи хоть варианты. интересно
так и пишешь, удалить записи, для которых существуют дубликаты. Ну и какой-нибудь элемент из группы дубликатов оставляешь, например, с меньшим ID-шником.
delete from tbl
where not id in (select min(id) from tbl group by user, thing)
where not id in (select min(id) from tbl group by user, thing)
Ребята имели в виду
А я имел в виду MySQL:
DELETE FROM
TBL
WHERE
ID IN
(
SELECT A.ID FROM
TBL A,
TBL B
WHERE
A.User=B.User
AND
A.Thing = B.Thing
AND
A.ID <> B.ID
)
AND
ID
NOT IN
(
SELECT MIN (A.ID) FROM
TBL A,
TBL B
WHERE
A.User=B.User
AND
A.Thing = B.Thing
AND
A.ID <> B.ID
)
А я имел в виду MySQL:
ALTER [b]IGNORE[/b] TABLE TBL ADD UNIQUE (User, Thing)
блеать, сработает?
Я лох
Я лох
в оракле сработает. если в мускуле есть IN, то должно сработать. я не помню.
есть
Но у тебя
not id in,
а у меня
id not in
Думаю, похуй
Но у тебя
not id in,
а у меня
id not in
Думаю, похуй
конечно одно ито же. это у меня выебоны.
Да, я точно лох
Но фикус с alter ignore мне понравился - это точно быстрее любых выборок
Но фикус с alter ignore мне понравился - это точно быстрее любых выборок
я имел ввиду вот это
DELETE FROM TBL
WHERE EXISTS ( SELECT 1
FROM TBL TBL2
WHERE TBL.User = TBL2.User
AND TBL.Thing = TBL2.Thing
AND TBL.ID > TBL2.ID )
ты только с альтером объясни. разве оно дубликаты удалит? я чот не очень мануал понял.
А вот тут как раз вопрос:
Удалятся только дубликаты или дубликаты вместе с оригиналами?
Удалятся только дубликаты или дубликаты вместе с оригиналами?
Удалит, мы попробовали, точно делает именно то, что надо. Но только в MySQL
для "оригиналов" вот это условие не выполняется
AND TBL.ID > TBL2.ID
AND TBL.ID > TBL2.ID
дадад, я как раз хотел оправдаться
да, нашел на русском. у тебя круче решение. я в альтере не силен. тем более мускульном.
а игнор как раз только там и есть
у меня фэйл. удаление из подзапросов - это расширение над ANSI.
link
link
Опачки:)
А не судьба с темп-таблицей? Мне дочитать лень:)
А не судьба с темп-таблицей? Мне дочитать лень:)
ну наверно можно создать таблицу, в нее инсертом залить данные и потом обратно. это пожалуй проще для понимания, но по времени дольше чем ребята написали.
а для тебя у меня тоже плохие новости. ignore - это тоже расширение
а для тебя у меня тоже плохие новости. ignore - это тоже расширение
для mssql 2005+
with cte as (
select
row_number over (partition by [user], thing order by Id) rn
from tbl
)
delete cte
where rn > 1
Ребята имели в видуребята или ты сам это придумал?
DELETE FROM
TBL
WHERE
ID IN
(
SELECT A.ID FROM
TBL A,
TBL B
WHERE
A.User=B.User
AND
A.Thing = B.Thing
AND
A.ID <> B.ID
)
AND
ID
NOT IN
(
SELECT MIN (A.ID) FROM
TBL A,
TBL B
WHERE
A.User=B.User
AND
A.Thing = B.Thing
AND
A.ID <> B.ID
)
у ребят тоже подзапрос. тоже пусть расслабятся. ответа верного никто пока не привел.
ну наверно можно создать таблицу, в нее инсертом залить данные и потом обратно.вместо обратной переливки можно старую таблицу drop-нуть, а временную переименовать в старую
какой ASNI имеется ввиду? в какой-нибудь 2003 даже row_number входит, имхо
можно. а теперь это все одним запросом...
я ваще хз. это нужно просто давно иметь дело с базами. когда модных наворотов не было.
вместо обратной переливки можно старую таблицу drop-нуть, а временную переименовать в старуювы всю таблицу собираетесь переливать, а дубликат может оказаться один на миллиард?
А че нельзя типа
select min id,a,b from tbl group by a,b
select min id,a,b from tbl group by a,b
в какой-нибудь 2003 даже row_number входитда в ISO SQL:2003 входит
http://en.wikipedia.org/wiki/Window_function_%28SQL%29#Limit...
Если DDL использовать, то подобное решение может быть быстрее (особенно, если есть FK - но их при удалении все равно надо будет обработать). Создать таблицу с такой же структурой, сделать switch old_table to new_table, вставить данные запросом с min/max. В общем, в любом случае, оптимальность решения только практика покажет.
PS MS SQL Server
PS MS SQL Server
Продолжайте, господа:)
Действительно интересны однострочные решения, которые займут времени не сильно больше переиндексации по одному из полей
Действительно интересны однострочные решения, которые займут времени не сильно больше переиндексации по одному из полей
а дубликат может оказаться один на миллиардименно
а может оказаться и полмиллиарда на миллиард
select
"это вынос мозга"
from tbl
"это вынос мозга"
from tbl
короче по счастливой случайности у меня оказался очень урезанный мускуль сервер. кстати скачанный совсем недавно с мускульного сайта 5.5.21. у меня нет даже row_number. так же не действуют никакие предложения умников из инета. банально не работает
delete from (select * from tbl) что вроде должно соответствовать delete from tbl.
так вот, все что я смог сделать - это
CREATE TABLE tbl1 AS select id, user, thing from tbl where id in (select min(id) from tbl group by user, thing)
кстати тот запрос что я привел первым тоже не работает. поскольку в условии не указано что нельзя создавать другую таблицу, то походу - это оно.
так
ALTER IGNORE TABLE tbl ADD UNIQUE (User, Thing)
у меня тоже не работает, к слову.
delete from (select * from tbl) что вроде должно соответствовать delete from tbl.
так вот, все что я смог сделать - это
CREATE TABLE tbl1 AS select id, user, thing from tbl where id in (select min(id) from tbl group by user, thing)
кстати тот запрос что я привел первым тоже не работает. поскольку в условии не указано что нельзя создавать другую таблицу, то походу - это оно.
так
ALTER IGNORE TABLE tbl ADD UNIQUE (User, Thing)
у меня тоже не работает, к слову.
CREATE TABLE tbl1 AS select id, user, thing from tbl where id in (select min(id) from tbl group by user, thing)
CREATE TABLE tbl1 AS SELECT min(id) as id, user, thing FROM tbl GROUP BY user, thing
ну да. копипастил из кучи селектов, навставлял при этом ошибок. все исправил кроме этого.
бля, я сделал это. давайте мою гребаную печеньку.
DELETE from tbl WHERE not EXISTS (
SELECT q.ID FROM (
select min(b.id) id from tbl b group by b.user, b.thing
) q where tbl.id = q.id
);
DELETE from tbl WHERE not EXISTS (
SELECT q.ID FROM (
select min(b.id) id from tbl b group by b.user, b.thing
) q where tbl.id = q.id
);
вот же ж:)
Как, оказывается, всё depends от реализации и версии
Ну, лови, раз обещал:

Как, оказывается, всё depends от реализации и версии
Ну, лови, раз обещал:

может по
rowid?
Хотя это будет не анси, они у всех по разному декларируются, зато не привязаны ко всяким суррогатным ID
delete from table_1 a where rowid not in (select min(rowid user, thing from table_1 b where a.user = b.user and a.thing = b.thing group by user, thing)
rowid?
Хотя это будет не анси, они у всех по разному декларируются, зато не привязаны ко всяким суррогатным ID
delete from table_1 a where rowid not in (select min(rowid user, thing from table_1 b where a.user = b.user and a.thing = b.thing group by user, thing)
может по
rowid?
Хотя это будет не анси, они у всех по разному декларируются, зато не привязаны ко всяким суррогатным ID
Вроде rowid неуникальны в случае кластерной таблицы.
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUES...
Оставить комментарий
uncle17
ЕстьTBL:
ID primary key
User int
Thing int
На User,Thing не поставлен UNIQUE
Как одним ANSI-запросом вычистить дубликаты, которые появились? У кого какие идеи? Чисто сравнить