2012-03-11 7 views
1

У меня есть таблица с четырьмя полями: идентификатор auto increment, строка и два целых числа. Я хочу сделать что-то в этом роде:Как удалить дубликаты из базы данных?

 select count(*) from table group by string 

, а затем использовать результат, чтобы консолидировать все счетчики, которые больше, чем 1.

То есть, взять все строки, которые имеют рассчитывать больше, чем 1, и замените все эти строки в базе данных (которые имеют одну и ту же строку) с одной строкой, идентификатор не имеет значения, а два целых числа - это сумма по всем строкам всех строк со счетом больше 1.

Возможно ли это с помощью нескольких простых запросов?

Спасибо.

ответ

0

Если вы можете остановить просмотр таблицы другими пользователями, то это довольно просто.

-- We're going to add records before deleting old ones, so keep track of which records are old. 
DECLARE @OldMaxID INT 
SELECT @OldMaxID = MAX(ID) FROM table 

-- Combine duplicate records into new records 
INSERT table (string, int1, int2) 
SELECT string, SUM(int1), SUM(int2) 
FROM table 
GROUP BY string 
HAVING COUNT(*) > 1 

-- Delete records that were used to make combined records. 
DELETE FROM table 
WHERE ID <= @OldMaxID 
GROUP BY string 
HAVING COUNT(*) > 1 
0

Существует простой способ сделать это. Просто поместите что-то вроде

id NOT IN (select id from table group by string) 

в вашем где заявление, которое будет выбирать только дублирует

0

Пуск, выбрав только те, с count > 0 и выбора суммы, которые вы хотите:

select * from (
    select count(*), string_col, sum(int_col_1), sum(int_col_2) 
    from my_table 
    group by string_col 
) as foo where count > 1 

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

2

Я бы предложил вставить во временную таблицу данные, сгруппированные по строке И, сопровождаемые min (id), где есть дубликаты. Затем обновите исходную таблицу с суммами, где id = min (id), и удалите, где строки совпадают, а идентификаторы - нет.

insert into temp 
select string, min(id) id, sum(int1) int1, sum(int2) int2 
    from table 
    group by string 
having count(*) > 1 

update table, temp 
    set table.int1 = temp.int1, 
     table.int2 = temp.int2 
where table.id = temp.id 
-- Works because there is only one record given a string in temp 
delete table 
    where exists (select null from temp where temp.string = table.string and temp.id <> table.id) 

Резервная копия обязательна :-) и сделка также.

0

Вы можете сделать все это в двух запросах без временных таблиц. Но вам нужно повторно запускать запрос DELETE, поскольку он будет удалять только один дубликат за раз. Поэтому, если есть 3 копии строки, вам нужно будет запустить ее дважды. Но вы можете просто запустить его, пока результаты больше не получатся.

Обновите повторяющиеся строки, которые вы собираетесь хранить, чтобы содержать счет/сумму.

UPDATE tablename JOIN (
    SELECT min(id) id,sum(int1) int1,sum(int2) int2 
    FROM tablename GROUP BY string HAVING c>1 
) AS dups ON tablename.id=dups.id 
SET tablename.int1=dups.int1, tablename.int2 

Тогда вы можете использовать тот же запрос SELECT в запросе DELETE, используя синтаксис с несколькими таблицами.

DELETE tablename FROM tablename 
JOIN (SELECT max(id) AS id,count(*) c FROM tablename GROUP BY string HAVING c>1) dups 
ON tablename.id=dups.id 

Просто запустите этот УДАЛИТЬ, пока не будет возвращено строк (0 затронутых строк).

+0

это не соответствует требованию, чтобы целые числа в оставшейся строке обновлялись, чтобы иметь сумму всех целых чисел во всех строках группы (перед удалением) –

+0

спасибо, что указали это, пропустили эту часть вопроса. Отредактировано, чтобы добавить запрос UPDATE, чтобы сначала сохранить сумму. –

0

Вы можете получить эту информацию в ЗРЕНИЯ:

CREATE VIEW SummarizedData (StringCol, IntCol1, IntCol2, OriginalRowCount) AS 
    SELECT StringCol, SUM(IntCol1), SUM(IntCol2), COUNT(*) 
    FROM TableName 
    GROUP BY StringCol 

Это позволит создать виртуальную таблицу с информацией, которую вы хотите.Он будет содержать строки, для которых был только один экземпляр значений StringCol, - если вы действительно не хотите, чтобы они добавили фразу HAVING COUNT(*) > 1 в конец запроса.

С помощью этого метода вы можете сохранить исходную таблицу и просто прочитать из обобщенных данных или создать пустую структуру таблицы с соответствующими столбцами и INSERT от SummarizedData в свою новую таблицу, чтобы получить «реальную» таблицу с данными ,

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