Количество последовательных значений, начинающихся с первой позиции - PullRequest
0 голосов
/ 14 июня 2019

Я хочу знать, какой и сколько последовательных цветов с вершины стека, но только для этого начинается с позиции 1 сверху:

цветовая позиция в стеке

+   red   +  1
|   red   |  2
|   red   |  3     
|   blue  |  4     Stack A
|   blue  |  5
|   red   |  6
|   red   |  7 
+---------+      


|   red   |  1     Stack B  
+---------+     
|   blue  |  1
|   red   |  2
|   red   |  3     Stack C
|   blue  |  4
+---------+      

Таблица:

Stack   Color    position
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

Результат, которого я не получу

Stack    Color      Quantity
A        Red        3
B        Red        1
C        Blue       1 
  • У меня есть 3 последовательных красных, начиная с вершины в стеке. A
  • У меня есть 1 последовательный красный, начиная с вершины в стеке B
  • У меня 1 последовательный синий, начиная с вершины в стеке C

Ответы [ 2 ]

1 голос
/ 14 июня 2019

Короткая версия

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
0 голосов
/ 14 июня 2019

Это не должно рассматриваться как проблема пробелов и островков. Я думаю, что самое простое решение:

select stack, first_color, count(*)
from (select t.*,
             min(case when color <> first_color then position end) over (partition by stack) as first_other_color_position
      from (select t.*, first_value(color) over (partition by stack order by position) as first_color
            from t
           ) t
     ) t
where first_other_color_position is null or position < first_other_color_position
group by stack, first_color
order by stack;

Здесь - это дБ <> скрипка.

Логика проста:

  • Получить первый цвет для каждого стека.
  • Получить позицию первых строк для каждого, который не того цвета.
  • Используйте эту информацию для фильтрации и агрегирования данных.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...