Какой лучший способ удалить повторяющиеся записи в базе данных mysql с помощью запросов rails или mysql?
Как удалить дубликаты записей в базе данных mysql?
Ответ 1
Что вы можете сделать, это скопировать отдельные записи в новую таблицу:
select distinct * into NewTable from MyTable
Ответ 2
Здесь другая идея в каком-либо конкретном языке:
rs = `select a, b, count(*) as c from entries group by 1, 2 having c > 1`
rs.each do |a, b, c|
`delete from entries where a=#{a} and b=#{b} limit #{c - 1}`
end
Edit:
Престижность Olaf для подсказки "иметь":)
Ответ 3
Хорошо, если это небольшая таблица, из консоли rails вы можете сделать
class ActiveRecord::Base
def non_id_attributes
atts = self.attributes
atts.delete('id')
atts
end
end
duplicate_groups = YourClass.find(:all).group_by { |element| element.non_id_attributes }.select{ |gr| gr.last.size > 1 }
redundant_elements = duplicate_groups.map { |group| group.last - [group.last.first] }.flatten
redundant_elements.each(&:destroy)
Ответ 4
Проверить наличие повторяющихся записей:
SELECT DISTINCT(req_field) AS field, COUNT(req_field) AS fieldCount FROM
table_name GROUP BY req_field HAVING fieldCount > 1
Удалить повторяющиеся запросы:
DELETE FROM table_name
USING table_name, table_name AS vtable
WHERE
(table_name.id > vtable.id)
AND (table_name.req_field=req_field)
Заменить req_field и table_name - работать без проблем.
Ответ 5
Новое для SQL:-) Это классический вопрос, который часто задают в интервью:-) Я не знаю, будет ли он работать в MYSQL, но он работает в большинстве баз данных -
> create table t(
> a char(2),
> b char(2),
> c smallint )
> select a,b,c,count(*) from t
> group by a,b,c
> having count(*) > 1
a b c
-- -- ------ -----------
(0 rows affected)
> insert into t values ("aa","bb",1)
(1 row affected)
> insert into t values ("aa","bb",1)
(1 row affected)
> insert into t values ("aa","bc",1)
(1 row affected)
> select a,b,c,count(*) from t group by a,b,c having count(*) > 1
a b c
-- -- ------ -----------
aa bb 1 2
(1 row affected)
Ответ 6
Если у вас есть PK (id) в таблице (EMP) и вы хотите, чтобы старые удаляли дубликаты записей с столбцом имени. Для больших данных следующий запрос может быть хорошим подходом.
DELETE t3
FROM (
SELECT t1.name, t1.id
FROM (
SELECT name
FROM EMP
GROUP BY name
HAVING COUNT(name) > 1
) AS t0 INNER JOIN EMP t1 ON t0.name = t1.name
) AS t2 INNER JOIN EMP t3 ON t3.name = t2.name
WHERE t2.id < t3.id;
Ответ 7
предположим, что у нас есть имя таблицы tbl_product, и в поле p_pi_code и p_nats_id существует дубликат в максимальном количестве нет, тогда
сначала создайте новую таблицу, вставьте данные из существующей таблицы...
т.е. от tbl_product до newtable1, если что-то еще, то newtable1 до newtable2
CREATE TABLE `newtable2` (
`p_id` int(10) unsigned NOT NULL auto_increment,
`p_status` varchar(45) NOT NULL,
`p_pi_code` varchar(45) NOT NULL,
`p_nats_id` mediumint(8) unsigned NOT NULL,
`p_is_special` tinyint(4) NOT NULL,
PRIMARY KEY (`p_id`)
) ENGINE=InnoDB;
INSERT INTO newtable1 (p_status, p_pi_code, p_nats_id, p_is_special) SELECT
p_status, p_pi_code, p_nats_id, p_is_special FROM tbl_product group by p_pi_code;
INSERT INTO newtable2 (p_status, p_pi_code, p_nats_id, p_is_special) SELECT
p_status, p_pi_code, p_nats_id, p_is_special FROM newtable1 group by p_nats_id;
после этого мы видим, что все дубликаты в поле удалены
Ответ 8
Мне пришлось делать это недавно в Oracle, но в MySQL это было бы так же. Это было много данных, по крайней мере, по сравнению с тем, с чем я привык работать, поэтому мой процесс дедупликации был сравнительно тяжелым. Я включаю его здесь, если кто-то другой встретится с аналогичной проблемой.
У моих дублированных записей были разные идентификаторы, разные updated_at
раз, возможно разные ID updated_by
, но все остальные столбцы одинаковы. Я хотел сохранить последнее обновление любого дублированного набора.
Я использовал комбинацию логики Rails и SQL, чтобы сделать это.
Шаг первый: запустите rake script, чтобы идентифицировать идентификаторы дубликатов записей, используя логику модели. Идентификаторы идут в текстовом файле.
Шаг второй: создать временную таблицу с одним столбцом, идентификаторы для удаления, загруженные из текстового файла.
Шаг третий: создайте другую временную таблицу со всеми записями, которые я собираюсь удалить (на всякий случай!).
CREATE TABLE temp_duplicate_models
AS (SELECT * FROM models
WHERE id IN (SELECT * FROM temp_duplicate_ids));
Шаг четыре: фактическое удаление.
DELETE FROM models WHERE id IN (SELECT * FROM temp_duplicate_ids);
Ответ 9
Вы можете использовать:
http://lenniedevilliers.blogspot.com/2008/10/weekly-code-find-duplicates-in-sql.html
чтобы получить дубликаты, а затем просто удалить их с помощью кода Ruby или SQL-кода (я бы сделал это в SQL-коде, но это зависит от вас: -)
Ответ 10
Если ваша таблица имеет PK (или вы можете легко ее предоставить), вы можете указать любое количество столбцов в таблице, чтобы они были равны (чтобы квалифицировать как дубликат) со следующим запросом (может быть, немного беспорядочно но он работает):
DELETE FROM table WHERE pk_id IN(
SELECT DISTINCT t3.pk_id FROM (
SELECT t1.* FROM table AS t1 INNER JOIN (
SELECT col1, col2, col3, col4, COUNT(*) FROM table
GROUP BY col1, col2, col3, col4 HAVING COUNT(*)>1) AS t2
ON t1.col1 = t2.col1 AND t1.col2 = t2.col2 AND t1.col3 = t2.col3 AND
t1.col4 = t2.col4)
AS t3, (
SELECT t1.* FROM table AS t1 INNER JOIN (
SELECT col1, col2, col3, col4, COUNT(*) FROM table
GROUP BY col1, col2, col3, col4 HAVING COUNT(*)>1) AS t2
ON t1.col1 = t2.col1 AND t1.col2 = t2.col2 AND t1.col3 = t2.col3 AND
t1.col4 = t2.col4)
AS t4
WHERE t3.col1 = t4.col1 AND t3.pk_id > t4.pk_id
)
Это оставит первую запись, введенную в базу данных, удалив "самые новые" дубликаты. Если вы хотите сохранить последнюю запись, переключите > в <.
Ответ 11
В MySql, когда я помещаю что-то вроде
delete from A where IDA in (select IDA from A )
mySql сказал что-то вроде "вы не можете использовать ту же таблицу в выбранной части операции удаления".
Мне просто нужно удалить несколько повторяющихся записей, и мне удалось выполнить такую программу .php
<?php
...
$res = hacer_sql("SELECT MIN(IDESTUDIANTE) as IDTODELETE
FROM `estudiante` group by `LASTNAME`,`FIRSTNAME`,`CI`,`PHONE`
HAVING COUNT(*) > 1 )");
while ( $reg = mysql_fetch_assoc($res) ) {
hacer_sql("delete from estudiante where IDESTUDIANTE = {$reg['IDTODELETE']}");
}
?>
Ответ 12
Я использую Alter Table
ALTER IGNORE TABLE jos_city ADD UNIQUE INDEX(`city`);
Ответ 13
Я использовал @krukid ответ выше, чтобы сделать следующее на таблице с около 70 000 записей:
rs = 'select a, b, count(*) as c from table group by 1, 2 having c > 1'
# get a hashmap
dups = MyModel.connection.select_all(rs)
# convert to array
dupsarr = dups.map { |i| [i.a, i.b, i.c] }
# delete dups
dupsarr.each do |a,b,c|
ActiveRecord::Base.connection.execute("delete from table_name where a=#{MyModel.sanitize(a)} and b=#{MyModel.sanitize(b)} limit #{c-1}")
end
Ответ 14
Вот решение rails, с которым я столкнулся. Может быть, не самая эффективная, но не большая сделка, если ее одноразовая миграция.
distinct_records = MyTable.all.group(:distinct_column_1, :distinct_column_2).map {|mt| mt.id}
duplicates = MyTable.all.to_a.reject!{|mt| distinct_records.include? mt.id}
duplicates.each(&:destroy)
Сначала группы по всем столбцам, которые определяют уникальность, пример показывает 2, но вы могли бы иметь более или менее
Во-вторых, выбирает инверсию этой группы... все остальные записи
В-третьих, удаляет все эти записи.
Ответ 15
Сначала сделайте группу по столбцу, по которой вы хотите удалить дубликат. Но я не делаю этого с группой. Я пишу самосоединиться.
Вам не нужно создавать временную таблицу.
Удалить дубликат, кроме одной записи: В этой таблице должен быть столбец автоматического увеличения. Возможное решение, с которым я только что столкнулся:
DELETE n1 FROM names n1, names n2 WHERE n1.id > n2.id AND n1.name = n2.name
если вы хотите сохранить строку с наименьшим значением auto increment id или
DELETE n1 FROM names n1, names n2 WHERE n1.id < n2.id AND n1.name = n2.name
если вы хотите сохранить строку с наивысшим значением идентификатора автоматического увеличения.
Вы можете перекрестно проверить свое решение, снова найти дубликат:
SELECT * FROM `names` GROUP BY name, id having count(name) > 1;
Если он возвращает результат 0, запрос выполняется успешно.