注意 我认为您的问题是,如果两个或多个列值相等,则 2 个 行 被视为重复。如果您只是在 columns 中寻找同一行的重复值,@GordonLinoff 的答案更合适
在 MySQL 中布尔值实际上表示为 0 或 1
对于您的三列示例,条件
(a.col1 = b.col1) + (a.col2 = b.col2) + (a.col3 = b.col3) >= 2
应该做的伎俩
例如,假设您有一个唯一的id 列:
SELECT *
FROM your_table a
WHERE EXISTS (
SELECT 1
FROM your_table b
WHERE (a.col1 = b.col1) + (a.col2 = b.col2) + (a.col3 = b.col3) >= 2
AND a.id != b.id /** Don't consider the same row */
)
更新
对于 1k 和 130k 之间的大时差,我并不感到惊讶。我想规模将是线性的,因此 15s * 130/1 = 1950s,大约需要 30 分钟来查询整个表。
另外不要忘记,对于每一行,查询都会检查所有其他行是否有重复项。这就是为什么只获取整个表会更快的原因。
我希望您只需要一次性使用此查询来识别受骗者。如果不是,它将指向一些不确定的数据库设计,并且可能会重构该表以更好地适应其目的。这是@apokryfos 在他对您的问题的评论中所指的 XY 问题。
由于条件复杂,上述查询不允许在列上使用任何索引。
假设您在某些列上有单独的索引并且id 是表的 PK,则您可以可能使用UNION ALL 更快地获得结果。
SELECT base.*
FROM your_table base
JOIN (
SELECT a.id, 1 col_match
FROM your_table a
WHERE EXISTS (
SELECT 1
FROM your_table b
WHERE b.col1 = a.col1
AND b.id != a.id
)
UNION ALL
SELECT a.id, 1 col_match
FROM your_table a
WHERE EXISTS (
SELECT 1
FROM your_table b
WHERE b.col2 = a.col2
AND b.id != a.id
)
UNION ALL
SELECT a.id, 1 col_match
FROM your_table a
WHERE EXISTS (
SELECT 1
FROM your_table b
WHERE b.col3 = a.col3
AND b.id != a.id
)
) raw
ON raw.id = base.id
GROUP BY base.id
HAVING SUM(raw.col_match) >= 2
它可能看起来很庞大,但可以轻松地在应用层中为您的十多个列动态构建。
请记住,如果重复项多于唯一项,则颠倒此逻辑可能是有意义的。