在具有重复行的 SQL Server 表中按组查找行号

Posted

技术标签:

【中文标题】在具有重复行的 SQL Server 表中按组查找行号【英文标题】:find row number by group in SQL server table with duplicated rows 【发布时间】:2015-05-18 22:16:50 【问题描述】:

我需要在有一些重复的表中按组计算行号。

表:

id va1ue1 value2  
1   3974   39
1   3974   39
1   972    5
1   972    10

SQL:

 select id, value1, value2, COUNT(*) cnt
 FROM table
 group by id, value1, value2
 having COUNT(*)  > 1 

代码只计算重复的行。 我需要:

 id, value1, value2
 1   972      5      
 1   972      10     

我不需要计算重复的行,我只需要 value1 在 value2 列中具有多个不同值的行。

谢谢

【问题讨论】:

【参考方案1】:

使用DISTINCT:

select id, value1, count(distinct value2) cnt
from table
group by id, value1
having count(distinct value2)  > 1 

如果您想了解详细信息,那么:

select * from table t1
cross apply(select cnt from(
                            select count(distinct value2) cnt
                            from table t2 
                            where t1.id = t2.id and t1.value1 = t2.value1) t 
            where cnt > 1)ca

【讨论】:

【参考方案2】:

在 SQL Server 2008 中,您可以使用一种技巧来使用窗口函数对不同的值进行计数。您可能会发现这是一个不错的解决方案:

select t.id, t.value1, t.value2
from (select t.*, sum(case when seqnum = 1 then 1 else 0 end) over (partition by value1) as numvals
      from (select t.*, row_number() over (partition by value1, value2 order by (select null)) as seqnum
            from table t
           ) t
     ) t
where numvals > 1;

【讨论】:

COUNT(DISTINCT) OVER 是在哪个版本中修复的? @AndriyM 。 . .糟糕,我在考虑 Oracle。【参考方案3】:

在没有GROUP BY 的情况下尝试这种方式:

 select id, value1, value2
 FROM table AS T1
 where 1 < (
   select  COUNT(*) 
   FROM table AS T2
   where T1.value1 = T2.value1)

【讨论】:

【参考方案4】:

试试这个

;WITH    CTE
          AS ( SELECT   id ,
                        value1 ,
                        value2 ,
                        COUNT(*) cnt
               FROM     table
               GROUP BY id ,
                        value1 ,
                        value2
               HAVING   COUNT(*) > 1
             )
    SELECT  *
    FROM    table1
    WHERE   value1 IN ( SELECT  value1
                        FROM    CTE )

【讨论】:

【参考方案5】:

只需在HAVING 之后使用NOT,即可准确获取不重复的行。

 select id, value1, value2
 FROM [table]
 group by id, value1, value2
 having NOT COUNT(*)  > 1 

Fiddle here.

【讨论】:

【参考方案6】:

如果您想要表中的实际行,而不仅仅是符合条件的 id, value1 对,您可以这样做:

WITH discrepancies AS (
  SELECT,
    id,
    value1,
    value2,
    distinctcount = COUNT(DISTINCT value2) OVER (PARTITION BY id, value1)
  FROM
    dbo.atable
)
SELECT
  id,
  value1,
  value2
FROM
  discrepancies
WHERE
  distinctcount > 1
;

如果 SQL Server 2008 支持 COUNT(DISTINCT ...) 和 OVER clause。

基本上,这与Giorgi Nakeuri's one 的想法差不多,只是你不会多次上桌。

唉,到目前为止还有no support for COUNT(DISTINCT ...) OVER ... in SQL Server。不过,您可以使用不同的方法,它仍然允许您只触摸一次表格并返回详细信息行:

WITH discrepancies AS (
  SELECT,
    id,
    value1,
    value2,
    minvalue2 = MIN(value2) OVER (PARTITION BY id, value1),
    maxvalue2 = MAX(value2) OVER (PARTITION BY id, value1)
  FROM
    dbo.atable
)
SELECT
  id,
  value1,
  value2
FROM
  discrepancies
WHERE
  minvalue2 <> maxvalue2
;

这里的想法是每个id, value1 获得MIN(value2)MAX(value2) 并查看它们是否不同。如果是这样,则意味着您在此 id, value1 子集中存在差异,并且您希望返回该行。

该方法利用带有 OVER 子句的聚合来避免自连接,这正是表在此处仅访问一次的原因。

【讨论】:

以上是关于在具有重复行的 SQL Server 表中按组查找行号的主要内容,如果未能解决你的问题,请参考以下文章

在 Pandas 数据框中按组过滤具有最小值的行 [重复]

在SQL中按组计算移动平均数

如何查找在 SQL Server 表中插入或更新行的时间

如何从 sql server 2008 中具有不同 TaskIds 的表中查找日期?

如何在mysql中按组查找累积值?

在数据框中按组折叠文本[重复]