题
如果我有一个包含重要两列的表,
CREATE TABLE foo (id INT, a INT, b INT, KEY a, KEY b);
我怎样才能找到同时具有这两者的所有行 a
和 b
两行相同吗?例如,在这个数据集中
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”即可。将两列放入新表中,删除旧表中的所有数据,然后将临时值复制回来。