【发布时间】:2010-10-15 20:53:28
【问题描述】:
我有一个包含 varchar 列的表,我想在该列中查找所有具有重复值的记录。我可以用来查找重复项的最佳查询是什么?
【问题讨论】:
-
既然您提到查找所有记录,我假设您需要知道该 varchar 列中的 KEYS 以及重复的 VALUES。
-
得到值后我可以很容易地找到键,我真的只是想要一个所有重复值的列表。
标签: mysql
我有一个包含 varchar 列的表,我想在该列中查找所有具有重复值的记录。我可以用来查找重复项的最佳查询是什么?
【问题讨论】:
标签: mysql
使用GROUP BY 子句执行SELECT。假设 name 是您要在其中查找重复项的列:
SELECT name, COUNT(*) c FROM table GROUP BY name HAVING c > 1;
这将返回第一列中带有 name 值的结果,并计算该值在第二列中出现的次数。
【讨论】:
GROUP_CONCAT(id),它会列出ID。例如,请参阅我的答案。
ERROR: column "c" does not exist LINE 1是什么意思?
SELECT varchar_col
FROM table
GROUP BY varchar_col
HAVING COUNT(*) > 1;
【讨论】:
IN()/NOT IN()。
SELECT *
FROM mytable mto
WHERE EXISTS
(
SELECT 1
FROM mytable mti
WHERE mti.varchar_column = mto.varchar_column
LIMIT 1, 1
)
此查询返回完整记录,而不仅仅是不同的 varchar_column's。
此查询不使用COUNT(*)。如果有很多重复,COUNT(*) 很昂贵,你不需要整个COUNT(*),你只需要知道是否有两行具有相同的值。
这是通过相关查询底部的LIMIT 1, 1 实现的(本质上意味着“返回第二行”)。只有在上述第二行存在时,EXISTS 才会返回 true(即,至少有两行具有相同的 varchar_column 值)。
在varchar_column 上有一个索引当然会大大加快这个查询的速度。
【讨论】:
ORDER BY varchar_column DESC。
GROUP BY 和HAVING 只返回一个可能的重复项。此外,使用索引字段而不是COUNT(*) 的性能,以及ORDER BY 对重复记录进行分组的可能性。
根据 levik 的回答来获取重复行的 ID,如果您的服务器支持,您可以执行 GROUP_CONCAT(这将返回一个逗号分隔的 ID 列表)。
SELECT GROUP_CONCAT(id), name, COUNT(*) c
FROM documents
GROUP BY name
HAVING c > 1;
【讨论】:
SELECT id, GROUP_CONCAT(id), name, COUNT(*) c [...] 它启用内联编辑,并且它应该更新所有涉及的行(或至少第一个匹配的行),但不幸的是,编辑会生成一个Javascript 错误...
为了获取所有包含重复的数据,我使用了这个:
SELECT * FROM TableName INNER JOIN(
SELECT DupliactedData FROM TableName GROUP BY DupliactedData HAVING COUNT(DupliactedData) > 1 order by DupliactedData)
temp ON TableName.DupliactedData = temp.DupliactedData;
TableName = 您正在使用的表。
DupliactedData = 您要查找的重复数据。
【讨论】:
假设您的表名为 TableABC 并且您想要的列是 Col 并且 T1 的主键是 Key。
SELECT a.Key, b.Key, a.Col
FROM TableABC a, TableABC b
WHERE a.Col = b.Col
AND a.Key <> b.Key
与上述答案相比,这种方法的优势在于它提供了密钥。
【讨论】:
SELECT *
FROM `dps`
WHERE pid IN (SELECT pid FROM `dps` GROUP BY pid HAVING COUNT(pid)>1)
【讨论】:
要查找Employee中name列有多少条记录重复,下面的查询很有帮助;
Select name from employee group by name having count(*)>1;
【讨论】:
进一步了解@maxyfc's answer,我需要找到所有返回带有重复值的行,以便我可以在MySQL Workbench 中编辑它们:
SELECT * FROM table
WHERE field IN (
SELECT field FROM table GROUP BY field HAVING count(*) > 1
) ORDER BY field
【讨论】:
我的最终查询在此处包含了一些有帮助的答案 - 结合 group by、count 和 GROUP_CONCAT。
SELECT GROUP_CONCAT(id), `magento_simple`, COUNT(*) c
FROM product_variant
GROUP BY `magento_simple` HAVING c > 1;
这提供了两个示例的 ID(逗号分隔)、我需要的条形码以及重复的数量。
相应地更改表和列。
【讨论】:
我没有看到任何 JOIN 方法,它们在重复方面有很多用途。
这种方法会给您带来实际翻倍的结果。
SELECT t1.* FROM my_table as t1
LEFT JOIN my_table as t2
ON t1.name=t2.name and t1.id!=t2.id
WHERE t2.id IS NOT NULL
ORDER BY t1.name
【讨论】:
我看到了上面的结果,如果您需要检查重复的单列值,查询将正常工作。例如电子邮件。
但是,如果您需要检查更多列并希望检查结果的组合,那么此查询将正常工作:
SELECT COUNT(CONCAT(name,email)) AS tot,
name,
email
FROM users
GROUP BY CONCAT(name,email)
HAVING tot>1 (This query will SHOW the USER list which ARE greater THAN 1
AND also COUNT)
【讨论】:
SELECT COUNT(CONCAT(userid,event,datetime)) AS total, userid, event, datetime FROM mytable GROUP BY CONCAT(userid, event, datetime ) HAVING total>1
SELECT t.*,(select count(*) from city as tt
where tt.name=t.name) as count
FROM `city` as t
where (
select count(*) from city as tt
where tt.name=t.name
) > 1 order by count desc
用您的表格替换 city。 将 name 替换为您的字段名称
【讨论】:
我更喜欢使用窗口函数(MySQL 8.0+)来查找重复项,因为我可以看到整行:
WITH cte AS (
SELECT *
,COUNT(*) OVER(PARTITION BY col_name) AS num_of_duplicates_group
,ROW_NUMBER() OVER(PARTITION BY col_name ORDER BY col_name2) AS pos_in_group
FROM table
)
SELECT *
FROM cte
WHERE num_of_duplicates_group > 1;
【讨论】:
SELECT
t.*,
(SELECT COUNT(*) FROM city AS tt WHERE tt.name=t.name) AS count
FROM `city` AS t
WHERE
(SELECT count(*) FROM city AS tt WHERE tt.name=t.name) > 1 ORDER BY count DESC
【讨论】:
下面会找到所有使用过多次的product_id。每个 product_id 只能获得一条记录。
SELECT product_id FROM oc_product_reward GROUP BY product_id HAVING count( product_id ) >1
代码取自:http://chandreshrana.blogspot.in/2014/12/find-duplicate-records-based-on-any.html
【讨论】:
CREATE TABLE tbl_master
(`id` int, `email` varchar(15));
INSERT INTO tbl_master
(`id`, `email`) VALUES
(1, 'test1@gmail.com'),
(2, 'test2@gmail.com'),
(3, 'test1@gmail.com'),
(4, 'test2@gmail.com'),
(5, 'test5@gmail.com');
QUERY : SELECT id, email FROM tbl_master
WHERE email IN (SELECT email FROM tbl_master GROUP BY email HAVING COUNT(id) > 1)
【讨论】:
我由此改进:
SELECT
col,
COUNT(col)
FROM
table_name
GROUP BY col
HAVING COUNT(col) > 1;
【讨论】:
SELECT DISTINCT a.email FROM `users` a LEFT JOIN `users` b ON a.email = b.email WHERE a.id != b.id;
【讨论】:
a.email 更改为 a.* 并获取所有重复行的 ID。
SELECT DISTINCT a.* 几乎立即解决。
SELECT ColumnA, COUNT( * )
FROM Table
GROUP BY ColumnA
HAVING COUNT( * ) > 1
【讨论】:
要删除具有多个字段的重复行,首先将它们与为唯一不同的行指定的新唯一键相结合,然后使用“分组依据”命令删除具有相同新唯一键的重复行:
Create TEMPORARY table tmp select concat(f1,f2) as cfs,t1.* from mytable as t1;
Create index x_tmp_cfs on tmp(cfs);
Create table unduptable select f1,f2,... from tmp group by cfs;
【讨论】:
CREATE TEMPORARY TABLE ...?对您的解决方案进行一些解释会很棒。
一个非常晚的贡献...以防万一它对任何人有所帮助...我的任务是在银行应用程序中找到匹配的交易对(实际上是账户到账户转账的双方),以确定每个账户间转账交易的“发件人”和“收件人”,所以我们最终得到了:
SELECT
LEAST(primaryid, secondaryid) AS transactionid1,
GREATEST(primaryid, secondaryid) AS transactionid2
FROM (
SELECT table1.transactionid AS primaryid,
table2.transactionid AS secondaryid
FROM financial_transactions table1
INNER JOIN financial_transactions table2
ON table1.accountid = table2.accountid
AND table1.transactionid <> table2.transactionid
AND table1.transactiondate = table2.transactiondate
AND table1.sourceref = table2.destinationref
AND table1.amount = (0 - table2.amount)
) AS DuplicateResultsTable
GROUP BY transactionid1
ORDER BY transactionid1;
结果是DuplicateResultsTable 提供了包含匹配(即重复)事务的行,但它在第二次匹配同一对时也反向提供了相同的事务 id,因此外部 SELECT 用于分组通过第一个事务 ID,这是通过使用 LEAST 和 GREATEST 来确保两个事务 ID 在结果中的顺序始终相同,这使得 GROUP 第一个事务是安全的,从而消除了所有重复的匹配项。在不到 2 秒的时间内浏览近 100 万条记录并识别出 12,000 多个匹配项。当然 transactionid 是主索引,这真的很有帮助。
【讨论】:
Select column_name, column_name1,column_name2, count(1) as temp from table_name group by column_name having temp > 1
【讨论】:
如果你想删除重复使用DISTINCT
否则使用此查询:
SELECT users.*,COUNT(user_ID) as user FROM users GROUP BY user_name HAVING user > 1;
【讨论】:
作为 Levik 答案的一种变体,它允许您也找到重复结果的 id,我使用了以下内容:
SELECT * FROM table1 WHERE column1 IN (SELECT column1 AS duplicate_value FROM table1 GROUP BY column1 HAVING COUNT(*) > 1)
【讨论】:
感谢@novocaine 的出色回答,他的解决方案对我有用。我稍微改变了它以包含重复值的百分比,这在我的情况下是必需的。下面是修改后的版本。它将百分比减少到两个小数位。如果将 ,2 更改为 0,则不显示小数,更改为 1,则显示一位小数,依此类推。
SELECT GROUP_CONCAT(id), name, COUNT(*) c,
COUNT(*) OVER() AS totalRecords,
CONCAT(FORMAT(COUNT(*)/COUNT(*) OVER()*100,2),'%') as recurringPecentage
FROM table
GROUP BY name
HAVING c > 1
【讨论】:
尝试使用此查询:
SELECT name, COUNT(*) value_count FROM company_master GROUP BY name HAVING value_count > 1;
【讨论】: