Sql 查找多个列的重复项独占ID列

Sql 查找多个列的重复项独占ID列,sql,sql-server,sql-server-2005,tsql,duplicates,Sql,Sql Server,Sql Server 2005,Tsql,Duplicates,我已经找到了很多关于如何查找重复项的答案,包括PK列或不关注它,如下所示: 如果您有一个名为T1的表,列是c1、c2和c3,那么此查询将显示重复的值 SELECT C1, C2, C3, count(*)as DupCount from T1 GROUP BY C1, C2, C3 HAVING COUNT(*) > 1 但更常见的要求是获取所有具有相同c1、c2、c3值的副本的ID 因此,我需要以下不起作用的内容,因为必须聚合id: SELECT ID from T1 GRO

我已经找到了很多关于如何查找重复项的答案,包括PK列或不关注它,如下所示:

如果您有一个名为T1的表,列是c1、c2和c3,那么此查询将显示重复的值

SELECT C1, C2, C3, count(*)as DupCount
 from T1
 GROUP BY C1, C2, C3
 HAVING COUNT(*) > 1
但更常见的要求是获取所有具有相同c1、c2、c3值的副本的ID

因此,我需要以下不起作用的内容,因为必须聚合id:

SELECT ID
 from T1
 GROUP BY C1, C2, C3
 HAVING COUNT(*) <> 1
选择ID
从T1开始
按C1、C2、C3分组
有计数(*)1
(所有副本的ID必须不同,但列必须相等)

编辑


谢谢大家。我总是惊讶于人们在Stackoverflow上给出优秀答案的速度

我不完全理解你的问题,但这里有一个不同风格的解决方案:

;WITH CTE
     AS (SELECT ID,
                C1,
                C2,
                C3,
                COUNT(*) OVER (PARTITION BY C1, C2, C3) AS Cnt
         FROM   T1)
SELECT ID,
       C1,
       C2,
       C3
FROM   CTE
WHERE  Cnt > 1  
select id
from t1 a
join t1 b on a.c1 = b.c2
join t1 c on b.c2 = c.c3
where a.id <> b.id and b.id <> c.id and a.id <> c.id
选择id
从t1到a
在a.c1=b.c2上连接t1和b
在b.c2=c.c3上连接t1和c
其中a.id b.id和b.id c.id和a.id c.id

要获取所有重复的行,请执行以下操作:

使用以下命令:

WITH Dups AS
(
    SELECT *, 
           COUNT(1) OVER(PARTITION BY C1, C2, C3) AS CNT
      FROM T1  
)
SELECT * 
  FROM Dups
 WHERE CNT > 1
要获得唯一行(即保留一行并过滤其他重复行),请使用以下命令:

WITH NoDups AS
(
    SELECT *, 
         ROW_NUMBER() OVER(PARTITION BY C1, C2, C3 ORDER BY ID) AS RN
      FROM T1  
)
SELECT * 
  FROM NoDups
WHERE RN = 1 

假设CTE至少有SQL 2005:

;with cteDuplicates as (
    select c1, c2, c3
        from t1
        group by c1, c2, c3
        having count(*) > 1
)
select id
    from t1
        inner join cteDuplicates d
            on t1.c1 = d.c1
                and t1.c2 = d.c2
                and t1.c3 = d.c3

您可以将重复的C1、C2、C3组合存储到临时表中,然后将其加入以获取ID

select C1, C2, C3
into #duplicates
from T1
group by C1, C2, C3
having count(*) > 1

select ID
from T1 t
inner join #duplicates d
    on  t.C1 = d.C1
    and t.C2 = d.C2
    and t.C3 = d.C3

这里有很多建议的版本,但我想我想出了一个新的

select *
from @T as T1
where exists (select *
              from @T as T2
              where
                T1.ID <> T2.ID and
                T1.C1 = T2.C1 and
                T1.C2 = T2.C2 and
                T1.C3 = T2.C3)
选择*
从@T到T1
存在的位置(选择*
从@T到T2
哪里
T1.ID T2.ID和
T1.C1=T2.C1和
T1.C2=T2.C2和
T1.C3=T2.C3)

你能提供一些示例数据吗?这个答案假设sql server>=2005?@Nathan-Yep。现在是2011年,如果OP需要2000兼容的解决方案,他们应该在问题中说明@马丁:当然可以,但我是否错过了问题中的sqlserver,或者可以假设是这样的:非常感谢,只有25秒。45分钟后我取消了第一次进近;)与需要25秒的递归cte相比,您的方法只需要11秒。@Tim-它们不是递归cte。它们是使用窗口聚合函数的CTE@Mikael+1检查是否存在是这里所需要的全部。