You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

按两列之一分组数据库行:高效查找重复行的SQL查询方案

解决MySQL/MariaDB中按A或B列查找重复行的高效方案

嘿,我明白你遇到的问题了——原来的子查询方法在处理8万多行数据时慢得离谱,而且逻辑上也不够严谨。咱们来一步步优化这个需求:找出Column A值重复,或者Column B值重复的行,并且返回每组重复行中的任意一条,同时给出重复计数。

为什么你的原查询速度慢?

你原来用的是关联子查询,每一行数据都会触发一次子查询去统计count(*),84000行就意味着要跑84000次查询,相当于重复扫描表几万次,性能能好才怪!而且如果某行的A和B都有重复,这个count还会把两种重复的数量叠加,结果可能不符合预期。

高效优化方案

核心思路是先预统计所有重复的A值和B值,再关联回原表,这样只需要扫描表2次(分别统计A和B的重复),再加上索引的加持,速度会快很多。

第一步:给A、B列建索引(关键!)

先给A和B列单独建索引,这样分组统计重复值的时候可以直接用索引,不用全表扫描:

CREATE INDEX idx_table_a ON table_name(a);
CREATE INDEX idx_table_b ON table_name(b);

第二步:查询重复行(返回每组任意一条)

下面的SQL会找出所有A或B重复的组,然后每个组返回一行(这里取每组id最小的行,你也可以改成MAX(id)取最大的):

SELECT 
    t.id, 
    t.name, 
    t.a, 
    t.b, 
    dg.cnt AS duplicate_count
FROM (
    -- 统计所有重复的A值及其数量
    SELECT 'a' AS group_type, a AS group_value, COUNT(*) AS cnt 
    FROM table_name 
    GROUP BY a 
    HAVING cnt > 1
    UNION ALL
    -- 统计所有重复的B值及其数量
    SELECT 'b' AS group_type, b AS group_value, COUNT(*) AS cnt 
    FROM table_name 
    GROUP BY b 
    HAVING cnt > 1
) dg
-- 关联原表,找到对应组的行
JOIN table_name t 
    ON (dg.group_type = 'a' AND t.a = dg.group_value) 
    OR (dg.group_type = 'b' AND t.b = dg.group_value)
-- 每个重复组只返回一行(这里取id最小的)
GROUP BY dg.group_type, dg.group_value
HAVING t.id = MIN(t.id);

用你的示例数据测试,会得到这样的结果:

idnameabduplicate_count
1Lorem ipsum1Donec2
2dolor sit2rhoncus2

如果想返回每组id最大的行,把MIN(t.id)改成MAX(t.id)就行,结果会是id=4和id=3,完全符合你的需求。

可选:避免同一行被多次返回

如果某一行的A和B同时存在重复(比如某行A=1且B=rhoncus,而A=1有2行、B=rhoncus有2行),上面的查询会把这行分到两个组里,导致重复返回。如果要避免这种情况,可以用下面的写法,确保每行只返回一次:

SELECT DISTINCT
    t.id, 
    t.name, 
    t.a, 
    t.b, 
    -- 优先取A的重复计数,没有的话取B的
    COALESCE(a_cnt.cnt, b_cnt.cnt) AS duplicate_count
FROM table_name t
LEFT JOIN (
    SELECT a, COUNT(*) AS cnt FROM table_name GROUP BY a HAVING cnt > 1
) a_cnt ON t.a = a_cnt.a
LEFT JOIN (
    SELECT b, COUNT(*) AS cnt FROM table_name GROUP BY b HAVING cnt > 1
) b_cnt ON t.b = b_cnt.b
-- 只保留A或B有重复的行
WHERE a_cnt.cnt IS NOT NULL OR b_cnt.cnt IS NOT NULL;

为什么这个方案更快?

  • 只需要扫描表2次来统计A和B的重复值,而不是8万多次
  • 利用索引快速完成分组统计,避免全表扫描
  • 关联操作的开销远低于大量的子查询

这个方案在MySQL 5.7和MariaDB 10.1上都能完美运行,完全适配你的环境。

内容的提问来源于stack exchange,提问作者Daan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 13:04:09