5

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

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 行。

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

4

8 回答 8

1
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

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

于 2009-09-17T04:55:55.443 回答
1

这不应该工作吗?

SELECT * FROM foo WHERE a = b

=== 编辑 ===

怎么样

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
于 2009-09-17T04:56:57.867 回答
1
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 列上有一个索引。

于 2009-09-17T05:02:35.347 回答
1

你能澄清一下你最终需要做什么吗?最佳解决方案可能取决于此(例如,您是否只想删除所有重复键行?)

一种方法是处理这个表(不确定 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
于 2009-09-17T05:13:44.300 回答
1

试试这个:

    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 中的重复行。

于 2009-09-17T05:29:05.283 回答
0

这是另一种方法

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

无论如何,即使我觉得它更具可读性,如果你有这么大的表,你应该检查执行计划,子查询在性能方面名声不好......

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

于 2009-09-17T05:15:57.573 回答
0

您的既定目标是删除所有重复的(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 的行。

于 2009-09-17T12:40:14.320 回答
0

如果 id 值在最终产品中根本不重要,也就是说,如果您可以将它们全部重新编号并且没问题,并且如果 id 是串行列,那么只需在两列上“选择不同”进入新表,删除旧表中的所有数据,然后将临时值复制回。

于 2009-09-17T12:47:07.117 回答