问题
I'm having trouble with something very similar to this question T-sql Reset Row number on Field Change
The solution to this question is perfect, works fine. Except when I try with multiple other 'custno', it breaks down.
What I mean by that:
custno moddate who
--------------------------------------------------
581827 2012-11-08 08:38:00.000 EMSZC14
581827 2012-11-08 08:41:10.000 EMSZC14
581827 2012-11-08 08:53:46.000 EMSZC14
581827 2012-11-08 08:57:04.000 EMSZC14
581827 2012-11-08 08:58:35.000 EMSZC14
581827 2012-11-08 08:59:13.000 EMSZC14
581827 2012-11-08 09:00:06.000 EMSZC14
581827 2012-11-08 09:04:39.000 EMSZC49 Reset row number to 1
581827 2012-11-08 09:05:04.000 EMSZC49
581827 2012-11-08 09:06:32.000 EMSZC49
581827 2012-11-08 09:12:03.000 EMSZC49
581827 2012-11-08 09:12:38.000 EMSZC49
581827 2012-11-08 09:14:18.000 EMSZC49
581827 2012-11-08 09:17:35.000 EMSZC14 Reset row number to 1
-- my new rows for example of problem
581829 2012-11-08 09:12:03.000 EMSZC14 1
581829 2012-11-08 09:12:38.000 EMSZC49 1
581829 2012-11-08 09:14:18.000 EMSZC49
581829 2012-11-08 09:17:35.000 EMSZC14 Reset row number to 1
The introduction of a new custno
breaks this solution, which works perfectly for the one custno
.
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
I'm sure it's only a little tweak to handle multiple custno's, but this is already way beyond my capabilities and I managed to make it work for my data but that was purely by replacing column and table names. Unfortunately don't have a detailed enough understanding to resolve the issue I have.
My data looks like
custno start_date value
effectively exactly the same. I want a Row/rank of 1 for every time the 'value' or 'who' changes, regardless if that value/who has been seen before. This is all relative to a custno
. And I do see instances where a value/who can return back to the same value as well. Again, solution above handled that 'repetition' just fine... but for the one custno
I'm thinking I just need to somehow add some sort of grouping by custno
in somewhere? Just not sure where or how
Thanks!
回答1:
This is a gaps and islands problem, and we can use the difference in row numbers method here:
WITH cte AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY custno ORDER BY moddate) rn1,
ROW_NUMBER() OVER (PARTITION BY custno, who ORDER BY moddate) rn2
FROM chr
)
SELECT custno, moddate, who,
ROW_NUMBER() OVER (PARTITION BY custno, rn1 - rn2 ORDER BY moddate) rn
FROM cte
ORDER BY
custno,
moddate;
Demo
For an explanation of the difference in row number method used here, rn1
is just a time-ordered sequence from 1 onwards, per customer, according to the data you have shown above. The rn2
sequence is partitioned additionally by who
. It is the case the difference between rn1
and rn2
will always have the same value, for each customer. It is with this difference that we then take a row number over the entire table to generate the sequence you actually want to see.
来源:https://stackoverflow.com/questions/61538370/reset-row-number-on-value-change-but-with-repeat-values-in-partition