分区更改时将记录分组并将行号作为奇数编号

时间:2017-12-29 20:38:44

标签: sql sql-server tsql

请参阅下面的DDL:

create table Test (RevObjId int, LegalPartyId int, IsPrimary int)

insert into Test (RevObjId, LegalPartyId, IsPrimary) values (10, 20, 0)
insert into Test (RevObjId, LegalPartyId, IsPrimary) values (10, 21, 0)
insert into Test (RevObjId, LegalPartyId, IsPrimary) values (10, 22, 1)
insert into Test (RevObjId, LegalPartyId, IsPrimary) values (11, 20, 1)
insert into Test (RevObjId, LegalPartyId, IsPrimary) values (11, 21, 0)
insert into Test (RevObjId, LegalPartyId, IsPrimary) values (12, 30, 1)
insert into Test (RevObjId, LegalPartyId, IsPrimary) values (13, 40, 0)

我正在寻找下面的输出:

RevObjId LegalPartyId IsPrimary RowNumber
10 22 1 1
10 20 0 2
10 21 0 3
11 20 1 5
11 21 0 6
12 30 1 7
13 40 0 9

当我使用以下查询时:

select RevObjId, 
       LegalPartyId, 
       IsPrimary, 
       row_number() over(partition by RevObjId order by RevObjId asc,IsPrimary desc,LegalPartyId asc) as RowNumber 
       from test;

我按顺序获取行号,每行增加1,行号在分区更改后重置。当分区(通过RevObjId)发生变化时,如何将行号更改为下一个奇数? 这是我的SQL小提琴 http://sqlfiddle.com/#!6/01d5c/22

我们需要行号之间的差距,因为我需要以下列格式生成报告。 enter image description here

这是我提出的一个支持问题: How to convert every other row to column in T-SQL?

2 个答案:

答案 0 :(得分:3)

对此的需求非常可疑,但我认为应该这样做。

你得到间隙的唯一时间是前一个分区有奇数行 - 然后差距为1行。因此,这将跟踪具有奇数行的先前分区的运行计数,并为每个此类分区的行号总数加1。

WITH T
     AS (SELECT RevObjId,
                LegalPartyId,
                IsPrimary,
                odd_adj = CASE
                            WHEN RevObjId = LEAD(RevObjId) 
                                    OVER (ORDER BY RevObjId ASC, IsPrimary DESC, LegalPartyId ASC)
                              THEN 0
                            ELSE ROW_NUMBER() /*We are in the last row of the partition so can use rownumber as a more efficient alternative to count*/
                                    OVER (PARTITION BY RevObjId ORDER BY IsPrimary DESC, LegalPartyId ASC)%2
                          END,
                RowNumber = ROW_NUMBER() 
                                OVER(ORDER BY RevObjId ASC, IsPrimary DESC, LegalPartyId ASC)
         FROM   test)
SELECT RevObjId,
       LegalPartyId,
       IsPrimary,
       RowNumber
           +  SUM(odd_adj) OVER (ORDER BY RevObjId 
                                 ROWS UNBOUNDED PRECEDING) 
           - odd_adj AS RowNumber /*odd_adj is only potentially non zero for the last row in each partition 
                                   - if we are in the last row and it is 1 we need to deduct it 
                                     as this is not a previous partition */
FROM   T; 

SQL Fiddle

答案 1 :(得分:0)

尝试如下

with groupcount as
(
  select RevObjId, (count(*) + 1)/ 2 * 2 as c
  from test
  group by RevObjId
), RevObjIdRN as
(
  select RevObjId, LegalPartyId, IsPrimary, 
         row_number() over (partition by RevObjId order by IsPrimary desc,LegalPartyId asc) as rn
  from test
)
select t2.RevObjId, t2.LegalPartyId, t2.IsPrimary, rn + relative
from (
  select RevObjId, sum(c) over (order by RevObjId) - c as relative
  from groupcount 
) t1  
join RevObjIdRN t2 on t1.RevObjId =  t2.RevObjId

sqlfiddle

解决方案基于以下部分:

with groupcount as
(
  select RevObjId, (count(*) + 1)/ 2 * 2 c
  from test
  group by RevObjId
)
select RevObjId, sum(c) over (order by RevObjId) - c as relative
from groupcount

返回每组row_numberRevObjId偏移量)的起始RevObjId。其余的只是为每个row_number()添加RevObjId到此偏移量。