Короткая версия
DENSE_RANK может использоваться, чтобы найти первый «островок» цветов в стеке и объединить его:
with islands as (
select stack,color,position,
position-dense_rank() over (partition by stack,color order by position) i
from @table
)
select stack,color,count(*) as Count
from islands
where i=0
group by stack,color
order by stack,color
Это производит:
stack color Count
A Red 3
B Red 1
C blue 1
Объяснение
Это известно как проблема островов - как найти «островки» с одинаковыми или последовательными значениями в наборе данных.
Здесь помогает Position
, поскольку он меняет поведение внутри каждого стека. Теперь нам нужно найти острова по цвету внутри стека. Мы можем сделать это, рассчитав DENSE_RANK по стеку и цвету.
declare @table table (Stack varchar(2),Color varchar(10),Position int)
insert into @table(Stack ,Color ,position)
values
('A','Red' ,1),
('A','Red' ,2),
('A','Red' ,3),
('A','blue' ,4),
('A','Blue' ,5),
('A','Red' ,6),
('A','Red' ,7),
('B','Red' ,1),
('C','blue' ,1),
('C','red' ,2),
('C','red' ,3),
('C','blue' ,4)
select
stack,color,position,
dense_rank() over (partition by stack,color order by position) as Rank
from @table
order by stack,position;
Результаты:
stack color position Rank
A Red 1 1
A Red 2 2
A Red 3 3
A blue 4 1
A Blue 5 2
A Red 6 4
A Red 7 5
B Red 1 1
C blue 1 1
C red 2 1
C red 3 2
C blue 4 2
Разница между плотным рангом и положением одинакова внутри каждого цвета. Мы можем использовать это для идентификации островов:
select
stack,color,position,
dense_rank() over (partition by stack,color order by position) as Rank,
position-dense_rank() over (partition by stack,color order by position) as Island
from @table
order by stack,position
Это дает:
stack color position Rank Island
A Red 1 1 0
A Red 2 2 0
A Red 3 3 0
A blue 4 1 3
A Blue 5 2 3
A Red 6 4 2
A Red 7 5 2
B Red 1 1 0
C blue 1 1 0
C red 2 1 1
C red 3 2 1
C blue 4 2 2
Теперь мы можем группировать по стопке, цвету и острову, чтобы получить окончательный результат:
with x as (
select stack,color,position,dense_rank() over (partition by stack,color order by position) r,
position-dense_rank() over (partition by stack,color order by position) i
from @table
)
select stack,color,count(*) as Count
from x
where i=0
group by stack,color
order by stack,color