T-sql Reset Row number on Field Change

前端 未结 4 943
生来不讨喜
生来不讨喜 2020-12-10 03:58

Similar to a recent post of mine \"t-sql sequential duration\"”, but not exactly the same, I want to reset the row number based on a change in column x (in my case, column \

相关标签:
4条回答
  • 2020-12-10 04:35

    The only solution I can think of is to use a cursor (ugh) and suffer through the RBAR process. NOT an elegant solution as the cursor will have to read in excess of 1m rows. Bummer.

    0 讨论(0)
  • 2020-12-10 04:44

    Instead of:

    PARTITION BY custno ORDER BY custno, moddate, who)
    

    try:

    PARTITION BY custno, who ORDER BY custno, moddate)
    
    0 讨论(0)
  • 2020-12-10 04:54

    If you are on SQL Server 2012 you can use LAG to compare value with previous row and you can use SUM and OVER to record the changes.

    with C1 as
    (
      select custno,
             moddate,
             who,
             lag(who) over(order by moddate) as lag_who
      from chr
    ),
    C2 as
    (
      select custno,
             moddate,
             who,
             sum(case when who = lag_who then 0 else 1 end) 
                over(order by moddate rows unbounded preceding) as change 
      from C1
    )
    select row_number() over(partition by change order by moddate) as RowID,
           custno,
           moddate,
           who
    from C2
    

    SQL Fiddle

    Update:

    A version for SQL Server 2005. It uses a recursive CTE and a temp table for intermediary storage of the data you need to iterate over.

    create table #tmp
    (
      id int primary key,
      custno int not null,
      moddate datetime not null,
      who varchar(10) not null
    );
    
    insert into #tmp(id, custno, moddate, who)
    select row_number() over(order by moddate),
           custno,
           moddate,
           who
    from chr;
    
    with C as
    (
      select 1 as rowid,
             T.id,
             T.custno,
             T.moddate,
             T.who,
             cast(null as varchar(10)) as lag_who
      from #tmp as T
      where T.id = 1
      union all
      select case when T.who = C.who then C.rowid + 1 else 1 end,
             T.id,
             T.custno,
             T.moddate,
             T.who,
             C.who
      from #tmp as T
        inner join C
          on T.id = C.id + 1
    )
    select rowid,
           custno,
           moddate,
           who
    from C
    option (maxrecursion 0);
    
    drop table #tmp;
    

    SQL Fiddle

    0 讨论(0)
  • 2020-12-10 04:57

    I had success with this issue by using Rank():

    SELECT RANK() OVER (PARTITION BY who ORDER BY custno, moddate) AS RANK
    

    This returned your desired results. I actually found this post trying to solve the same problem.

    0 讨论(0)
提交回复
热议问题