带有DISTINCT的ROW_NUMBER()

时间:2015-01-27 22:40:51

标签: sql sql-server distinct

我有一张票证分配表,显示票证在解决之前转移到的不同组。这是一个简化的表格:

asgn_grp | date   | ticket_id
---------|--------|----------
       A | 1-1-15 | 1
       A | 1-2-15 | 1
       B | 1-3-15 | 1
       A | 1-1-15 | 2
       C | 1-2-15 | 2
       B | 1-3-15 | 2
       C | 1-1-15 | 3
       B | 1-2-15 | 3

我需要计算分配故障单的第二个不同组的计数,这意味着我想知道一旦故障单从其中转出,内部转移不计算在内。因此,ticket 1的第二个不同组是Bticket 2Cticket 3B。我需要计算这些,所以我需要的最终结果是

asgn_grp | count
---------|-------
       B | 2
       C | 1

我试过

SELECT distinct top 2 asgn_grp, ROW_NUMBER() OVER (ORDER BY date) 

作为我的子查询并从中拉出第二个,但是当我添加ROW_NUMBER()时,它会弄乱我的不同。如果我从子查询中提取ROW_NUMBER(),我现在可以订购我的值,以确保在DISTINCT列表之后获得第二个值。

另外,如果我不清楚是什么,请告诉我。

4 个答案:

答案 0 :(得分:0)

首先,您需要为每张票证识别asgn_grp的常量值组。你可以用不同的行数来做到这一点。

然后,您需要为每个组排序。为此,请使用组中的最小日期。最后,您可以在日期使用dense_rank()对这些组进行排名以获得第二个组。

select asgn_grp, count(*)
from (select ticket_id, asgn_grp,
             dense_rank() over (partition by ticket_id order by grpdate) as seqnum
      from (select s.*, min(date) over (partition by ticket_id, asgn_grp, grp) as grpdate
            from (select s.*,
                         (row_number() over (partition by ticket_id order by date) -
                          row_number() over (partition by ticket_id, asgn_grp order by date)
                         ) as grp
                  from simplified s
                 ) s
           ) s
    ) s
where seqnum = 2
group by asgn_grp;

答案 1 :(得分:0)

不要使用distinct,请尝试两次使用group by

select asgn_grp, count(*) from (
    select * , row_number() over (partition by ticket_id order by min_date) rn
    from (
        select asgn_grp, ticket_id, min(date) min_date
        from Table1 group by asgn_grp, ticket_id
    ) t1 
) t2 where rn = 2
group by asgn_grp;

http://sqlfiddle.com/#!3/a0d1e

派生表t1包含每个asgn_grp的唯一ticket_id以及每个asgn_grp的最小日期。对于示例数据,t1具有以下行:

ASGN_GRP    TICKET_ID   MIN_DATE
A   1   January, 01 2015 00:00:00+0000
B   1   January, 03 2015 00:00:00+0000
A   2   January, 01 2015 00:00:00+0000
B   2   January, 03 2015 00:00:00+0000
C   2   January, 02 2015 00:00:00+0000
B   3   January, 02 2015 00:00:00+0000
C   3   January, 01 2015 00:00:00+0000

外部查询然后使用row_number()通过其min_date为asgn_grp中的每个ticket_id编号,并为t2生成以下内容

ASGN_GRP    TICKET_ID   MIN_DATE    RN
A   1   January, 01 2015 00:00:00+0000  1
B   1   January, 03 2015 00:00:00+0000  2
A   2   January, 01 2015 00:00:00+0000  1
C   2   January, 02 2015 00:00:00+0000  2
B   2   January, 03 2015 00:00:00+0000  3
C   3   January, 01 2015 00:00:00+0000  1
B   3   January, 02 2015 00:00:00+0000  2

此表格已根据RN = 2进行过滤,并按asgn_grp分组,以获取每个asgn_grp的计数。

答案 2 :(得分:0)

如果您需要为未更改的组分配计数为零的组,请使用外部联接而不是内部联接

 WITH TBL AS
 (
 SELECT A.*, ROW_NUMBER() OVER(PARTITION BY ticket_id ORDER BY asgn_grp) AS RN
 FROM TABLE AS A
 )

 SELECT A.ASSN_GRP, COUNT(*) AS CNT
 FROM TBL AS A
 INNER JOIN TBL AS B
 ON B.TICKET_ID = A.TICKET_ID
 AND A.RN = B.RN + 1 
 GROUP BY A.ASSGN_GRP

答案 3 :(得分:0)

如果您想知道为什么使用DISTINCT ROW_NUMBER()更改您的结果:

从那以后:

  

GROUP BY查询在计算之前聚合。 DISTINCT查询在聚合之前计算。

因此当您使用ROW_NUMBER() - 这是一个标量值时 - 如果查询先计算,您将拥有ROW_NUMBER()个结果的唯一字段,然后您的DISTINCT会在其中应用你的结果将找不到任何重复的行!


对于您的结果,您可以使用此查询

SELECT ticket_id, asgn_grp, 
    (SELECT COUNT([date]) FROM yourTable t WHERE t.asgn_grp = r.asgn_grp And t.ticket_id = r.ticket_id)
FROM (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY ticket_id ORDER BY [date]) As ra
    FROM (
        SELECT *, ROW_NUMBER() OVER (PARTITION BY ticket_id, asgn_grp ORDER BY [date] Desc) As rn 
        FROM yourTable) findingOldDates
    WHERE rn = 1) r
WHERE ra = 2