删除重复行 #2

3

我有一个非常大(约1,000,000行)的表,其中可能包含重复行(可能包含NULL值)。

我的目标是这样做:

  1. 只选择不同的行。
  2. 删除具有重复“id”字段的行。

让我们看一个表:

id | a | b    
1  | 2 | 3    
2  | 8 | 7    
3  | 9 | 10    
2  | 8 | 7    
3  | 20| 12

What I want to get is:

id | a | b    
1  | 2 | 3    
2  | 8 | 7

id为2的行只保留一份,而id为3的行已被删除。

我的想法是:

  1. SELECT DISTINCT id, a, b FROM table;从中获取不同的行。
  2. 以某种方式过滤(1)的结果,以删除重复的id。

最佳解决方案是什么?


2
我很好奇当你在SO的搜索框中输入sql remove duplicate rows时找到了什么。你得到了和我一样的四十页结果吗? :-) 抱歉,忍不住开个玩笑:请见http://stackoverflow.com/search?q=sql+remove+duplicate+rows - paxdiablo
1
第二行重复了两次,下面列出了它,但第一行没有重复两次,也在下面列出了。这有点令人困惑,我认为您的意思是只在下面列出第一行,或者可能是第一行和第三行? - Neil
@Neil,我认为2之所以幸存下来是因为内容相同。3被丢弃了,因为两个记录不同(换句话说,如果所有副本都相同,则保留一个id的副本,否则将其丢弃),这可能使我上面的讽刺评论不准确 :-) 如果情况确实如此,那么向Petr道歉。 - paxdiablo
1
@paxdiablo那么为什么会有1呢? - Neil
@paxdiablo 是的,那正是我想要的。相同的行将被保留,但具有重复ID和不同其他字段的行将被删除。 - Petr
显示剩余2条评论
3个回答

2

现在,问题稍微清晰了一些,第三个答案:

SELECT id, min(a) as a, min(b) as b
FROM (SELECT DISTINCT id, a, b FROM table) t
GROUP BY id
HAVING count(*) =1

问题在于表必须包含所有行。在选择数据时必须进行过滤... - Petr
@Petr,你的问题是:“2. 删除具有重复'id'字段的行。”这很令人困惑。 - jzd
我指的是“从 SELECT 结果中删除”,而不是从表本身删除。抱歉。 - Petr
@Petr,我已经更新了我的答案,但“从SELECT结果中删除”是说“选择较少的行”的奇怪方式。 - jzd

0
Petr,根据评论看来,您想要一个组合...
包括: - 所有仅出现一次的ID行 - 所有ID出现多次的行 - 并且记录中的其他字段都相同
排除: - 任何ID出现多次但其他字段不完全匹配的行。
select ID, min(a) a, min(b) b
    from YourTable
    group by ID
    having min(a) = max(a)
       and min(b) = max(b)

如果除了a和b以外还有更多的列需要进行比较,只需将相应的值添加到选择字段列表和相应的“having”中即可。根据您提供的数据示例,从查询返回的值将是:
ID  MIN(A)  MIN(B)    Having MIN(A)  MAX(A)  MIN(B)  MAX(B)
1    2        3                2        2       3      3 
2    8        7                8        8       7      7
3    9       10                9       20      10     12    

因此,行ID = 3将被丢弃,因为在两个列中的同一min()和max()上having将失败。然后,您可以将其复制到新表中。只需通过表格进行一次操作...


0

你能否重建数据库,或者如果不能,从原始数据构建一个新的,以id作为主键?SQL可以处理其余部分。


1
这应该放在注释中,而不是答案中。;-) - Chintan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接