如果我有一个包含重要两列的表,

CREATE TABLE foo (id INT, a INT, b INT, KEY a, KEY b);

我怎样才能找到同时具有这两者的所有行 ab 两行相同吗?例如,在这个数据集中

id | a | b
----------
1  | 1 | 2
2  | 5 | 42
3  | 1 | 42
4  | 1 | 2 
5  | 1 | 2
6  | 1 | 42

我想取回除以下之外的所有行 id=2 因为它是独一无二的 (a,b). 。基本上,我想找到所有有问题的行来阻止

ALTER TABLE foo ADD UNIQUE (a, b);

比 n^2 for 循环更好的东西会很好,因为我的表有 10M 行。

奖励积分 :如何删除除一行之外的所有行(我不在乎是哪一行,只要剩下一行)

有帮助吗?

解决方案

SELECT * 
FROM foo first
JOIN foo second
  ON ( first.a = second.a
       AND first.b = second.b ) 
  AND (first.id <> second.id )

应该提出所有行,其中多一行具有相同的a和b组合。

希望你有一个关于a和b列的索引。

其他提示

select * from foo where a = b

或者我错过了什么?

===

为清晰起见而更新:

select * from 
foo as a
inner join foo as b
on a.a = b.a AND b.a = b.b
and a.id != b.id

++++++++++ 在第三次清晰度编辑之后:

select f1.id
FROM foo as f1
INNER JOIN foo as f2
ON f1.a = f2.a AND f1.b=f2.b AND f1.id != f2.id

但是我被枪杀了,所以请自己检查一下。

试试这个:

    With s as (Select a,b from foo group by a,b having Count(1)>1)
Select foo.* from foo,s where foo.a=s.a and foo.b=s.b

此查询应在表foo中显示重复的行。

您能否澄清一下您最终需要做什么?最好的解决方案可能取决于那个(例如,您只是想删除所有重复密钥行?)

一种方法是处理这个表(不确定mySQL是否支持它,它来自SYBASE)如果你想要的只是唯一键行:

SELECT MIN(id), A, B FROM FOO GROUP BY A, B HAVING COUNT(*)>1

你的确切问题(虽然我有点不知道为什么你需要除id = 2之外的所有行)是:

SELECT F1.*  
FROM FOO F1 , 
     (SELECT A, B FROM FOO GROUP BY A, B HAVING COUNT(*)>1) F2
WHERE F1.A=F2.A and F1.B=F2.B

要删除所有重复项,您可以执行

DELETE FOO WHERE NOT EXISTS
(SELECT 1 from
    (SELECT MIN(id) 'min_id' FROM FOO GROUP BY A, B HAVING COUNT(*)>1) UINIQUE_IDS 
 WHERE id = min_id)

作为替代方案,你可以做到

  SELECT MIN(id) 'id', A, B INTO TEMPDB..NEW_TABLE 
  FROM FOO GROUP BY A, B HAVING COUNT(*)>1

  TRUNCATE TABLE FOO
  // Drop indices on FOO
  INSERT FOO SELECT * FROM NEW_TABLE
  // Recreate indices on FOO

不应该这样吗?

SELECT * FROM foo WHERE a = b

=== edit ===

怎么样

SELECT a, b FROM foo GROUP BY a, b HAVING COUNT(*) > 1

===在我放弃这个问题之前最终重新编辑===

SELECT foo.* FROM foo, (
   SELECT a, b FROM foo GROUP BY a, b HAVING COUNT(*) > 1
) foo2
WHERE foo.a = foo2.a AND foo.b = foo2.b

这是另一种方法

select * from foo f1 where exists(
  select * from foo f2 where
    f1.id != f2.id and
    f1.a = f2.a and
    f1.b = f2.b )

无论如何,即使我发现它更具可读性,如果你有一个如此庞大的表,你应该检查执行计划,子查询有一个涉及性能的坏名声......

你还应该考虑创建索引(显然没有unique子句)来加速查询...对于大型操作,有时最好花时间创建索引,执行更新然后删除索引。 ..在这种情况下,我猜(a,b)上的索引肯定会有很多帮助......

您既定的目标是删除所有重复的组合 (a,b). 。为此,您可以使用多表 DELETE:

DELETE t1
  FROM foo t1
  JOIN foo t2 USING (a, b)
 WHERE t2.id > t1.id

在运行之前,您可以检查哪些行将被 已删除 和:

SELECT DISTINCT t1.id
  FROM foo t1
  JOIN foo t2 USING (a, b)
 WHERE t2.id > t1.id

WHERE 子句是 t2.id > t1.id 它将删除除具有最高值的那个之外的所有内容 id. 。在你的情况下,只有行 id 等于 2、5 或 6 的值将保留。

如果id值在最终产品中根本不重要,也就是说,如果你可以对它们进行重新编号,那就没问题了,如果id是一个串行列,那么只需要“select distinct”即可。将两列放入新表中,删除旧表中的所有数据,然后将临时值复制回来。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top