【问题标题】:more efficient way to select duplicate users选择重复用户的更有效方法
【发布时间】:2023-01-11 21:44:40
【问题描述】:

我试图从用户的所有重复行中选择*,其中重复定义为两个用户共享相同的first_namelast_name。 (我需要处理其他可能不同的列)

我正在使用 MySQL 8.0.28。

我的第一次尝试是从字面上翻译我的要求:

select * from `users` AS u1 where exists (select 1 from `users` AS u2 WHERE `u2`.`first_name` = `u1`.`first_name` AND `u2`.`last_name` = `u1`.`last_name` AND `u2`.`id` != `u1`.`id`)

很明显,这有一个可怕的执行时间。

我当前的查询是

SELECT * from users where  Concat(first_name," ",last_name) IN (select Concat(first_name," ",last_name) from `users` GROUP BY first_name, last_name HAVING COUNT(*)>1)

这样效率要高得多,但 8000 条记录仍然需要 100 多毫秒。我想不使用 concat 的解决方案可以从索引中受益,并且不需要计算每一行的结果。

另外,我无法让group by 工作,因为我需要选择重复的所有行的所有列,而不仅仅是不同的first_namelast_name。也因为我不想禁用ONLY_FULL_GROUP_BY(不确定禁用它是否有帮助)。

是否有更有效、更正确的方法来选择这些重复的行?

【问题讨论】:

  • edit你的问题向我们展示你的表定义。如果它有一个主键(id 列),这将作为一种有效的方法来有效地解决您的问题。
  • @O.Jones Tim Biegeleisen 的答案已经在寻找,而且我认为从我的第一个查询中可以明显看出 id 是主键。我应该更明确一点吗?

标签: mysql sql duplicates


【解决方案1】:

我只想在这里使用聚合方法:

SELECT *
FROM users
WHERE (first_name, last_name) IN (
    SELECT first_name, last_name
    FROM users
    GROUP BY 1, 2
    HAVING COUNT(*) > 1
);

在 MySQL 8+ 上,我们也可以在这里使用 COUNT() 作为解析函数:

WITH cte AS (
    SELECT *, COUNT(*) OVER (PARTITION BY first_name, last_name) AS cnt
    FROM users
)

SELECT *
FROM cte
WHERE cnt > 1;

【讨论】:

  • 非常感谢,我已经尝试过类似于第一个查询的方法,但我当时一定是语法错误,并且认为它通常不起作用。有趣的是,在我的 8000 条记录样本中,PARTITION BY 查询比 CONCAT 查询执行得更差。但很高兴知道 count over partition by 之类的东西仍然存在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-29
  • 2012-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-18
  • 1970-01-01
相关资源
最近更新 更多