我有一个varchar列的表,我想找到在这个列中有重复值的所有记录。我可以使用什么查询来查找重复项?


当前回答

根据levik的回答来获取重复行的id,如果服务器支持的话,可以执行GROUP_CONCAT(这将返回一个以逗号分隔的id列表)。

SELECT GROUP_CONCAT(id), name, COUNT(*) c
FROM documents
GROUP BY name
HAVING c > 1;

其他回答

试着使用这个查询:

SELECT name, COUNT(*) value_count FROM company_master GROUP BY name HAVING value_count > 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

用你的表格替换城市。 将name替换为字段名

SELECT  *
FROM    mytable mto
WHERE   EXISTS
        (
        SELECT  1
        FROM    mytable mti
        WHERE   mti.varchar_column = mto.varchar_column
        LIMIT 1, 1
        )
ORDER BY varchar_column

这个查询返回完整的记录,而不仅仅是不同的varchar_column。

这个查询不使用COUNT(*)。如果有很多重复项,COUNT(*)是昂贵的,并且不需要整个COUNT(*),只需要知道是否有两行具有相同的值。

这是通过相关查询底部的LIMIT 1,1来实现的(本质上意味着“返回第二行”)。EXISTS只在前面提到的第二行存在时才返回true(即至少有两行具有相同的varchar_column值)。

当然,在varchar_column上建立索引将大大加快此查询的速度。

假设您的表名为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

与上面的答案相比,这种方法的优点是它给出了Key。

我更喜欢使用窗口函数(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;

DB小提琴演示