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 \
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.
Instead of:
PARTITION BY custno ORDER BY custno, moddate, who)
try:
PARTITION BY custno, who ORDER BY custno, moddate)
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
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.