2012-03-11 57 views
1

我有一个表有四个字段:ID自动增量,一个字符串和两个整数。 我想要做类似的东西:如何从数据库中删除重复项?

 select count(*) from table group by string 

,然后用结果来巩固它们是大于1

也就是说,走哪都行数大于1的所有指控,并将数据库中所有这些行(具有相同的字符串)替换为单行,ID无关紧要,并且这两个整数是所有行数大于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) 
在where语句

,这将通过选择只是count > 0些,然后选择所需的资金只选择复制

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 

后我会将这些数据放入临时表中,删除不需要的行,并将临时表中的数据插入原始表中。

2

我建议插入临时表数据按字符串分组,并伴有min(id)其中有重复的地方。然后更新原始表格,其中id = min(id),并删除字符串匹配但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查询,因为它一次只能删除1个重复项。所以如果一行有三份,你需要运行两次。但是你可以运行它直到没有更多的结果。

更新您要保留的重复行以包含计数/总和。

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 

然后,您可以在DELETE查询中使用同一个SELECT查询,使用多表语法。

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 

只需运行DELETE,直到没有行返回(0受影响的行)。

+0

这不符合要求,其余行中的整数被更新为具有该组中所有行的所有整数的总和(在删除之前) – 2012-03-12 00:06:07

+0

感谢您指出这一点,错过了这部分问题。编辑添加UPDATE查询以首先保存总和。 – 2012-03-12 02:25:12

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添加到查询的末尾。

有了这个方法,你可以保持原有的表和汇总数据只是读,也可以创建具有相应列从SummarizedData一个空表结构和INSERT到新表中得到一个“真正”的表中的数据。